zoukankan      html  css  js  c++  java
  • python的面向对象编程

    面向对象编程是一种程序的范式,它把程序看成是对不同对象的相互调用,对现实世界建立的一种模型。

    面向对象编程的基本思想,类和实例。类用于定义抽象对象,实例根据类的定义被创建出来。

    在python当中我们使用下面的方法来定义类(按照 Python 的编程习惯,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的。):

    class Python(object):
            pass

    我们实例化方法的话呢就使用:

    xaioming = Python()

    在面向对象之后呢我们要进行属性的设置。

    class Person:
        def _init__(self,name):
    self.name = name
    p1 = Person() p1.name = 'Bart' p2 = Person() p2.name = 'Adam' p3 = Person() p3.name = 'Lisa' L1 = [p1, p2, p3] L2 = sorted(L1, key=lambda x:x.name) print L2[0].name print L2[1].name print L2[2].name

    结果是:

    Adam
    Bart
    Lisa

    并且属性也可以像变量一样进行加减。

    在C++和java中都拥有面向对象编程,同时他们都具有构造函数这个东西,在Python当中也有类似于构造函数的东西。那就是__init__(self,属性),当创建实例时,__init__()方法被自动调用.

    >>> class Person:
        def __init__(self,name,gender,birth):
            self.name = name
            self.gender = gender
            self.birth = birth

    __init__() 方法的第一个参数必须是 self,并且是一定要添加的,如果不添加的话呢我们的系统就无法将参数给对应上,就会导致编译出错

    >>> class Person:
        def __init__(name):
            pass
    
        
    >>> xiao = Person("xiao")
    Traceback (most recent call last):
      File "<pyshell#11>", line 1, in <module>
        xiao = Person("xiao")
    TypeError: __init__() takes 1 positional argument but 2 were given

    我们在对Python进行编程的时候,如果我们类里面的属性不希望被外面看到的话,我们可以用一种方法,对这个属性进行封装。

    如果一个属性由双下划线开头(__),该属性就无法被外部访问。

    >>> class Person(object):
        def __init__(self,name,score):
            self.name = name
            self.__score = score
    
            
    >>> p = Person('Bob',59)
    >>> print (p.name)
    Bob
    >>> try:
        print (p.__score)
    except AttributeError:
        print ("attributeerror")
    
        
    attributeerror

    但是,如果一个属性以"__xxx__"的形式定义,那它又可以被外部访问了,以"__xxx__"定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不要把普通属性用"__xxx__"定义。

    以单下划线开头的属性"_xxx"虽然也可以被外部访问,但是,按照习惯,他们不应该被外部访问。

    实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。

    定义类属性可以直接在 class 中定义:

    >>> class Person(object):
        address = "Earth"
        def __init__(self,name):
            self.name = name
    
            
    >>> print (Person.address)
    Earth
    >>> p1 = Person('Bob')
    >>> print (p1.address)
    Earth

    由于Python是动态语言,类属性也是可以动态添加和修改的:

    >>> Person.address = 'China'
    >>> print (p1.address)
    China

    当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问

    >>> p2 = Person('Dean')
    >>> print (p2.address)
    China
    >>> p1.address = 'Japanese'
    >>> print (p1.address)
    Japanese
    >>> print (p2.address)
    China

    在实例上面修改类属性不是更改类的属性,只是给这个类新添加了一个属性而已。

    虽然私有属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。

    >>> class People(object):
        def __init__(self,name,age):
            self.name = name
            self.__age = age
        def get_age(self):
            return self.__age
    
        
    >>> p1 = People('Dean',16)
    >>> p1.get_age()
    16

    在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。

    我们在class中定义的实例方法其实也是属性,它实际上是一个函数对象。

    >>> class People(object):
        def __init__(self,name,age):
            self.name = name
            self.__age = age
        def get_age(self):
            return self.__age
    
        
    >>> p1 = People('Dean',16)
    >>> p1.get_age()
    16
    >>> p1.get_age
    <bound method People.get_age of <__main__.People object at 0x0354CE10>>

    因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法

    >>> class People(object):
        def __init__(self,name,age):
            self.name = name
            self.__age = age
        def get_age(self):
            return self.__age
    
        
    >>> def fn_get_age(self):
        if self.get_age()>=60:
            return 'old'
        else:
            return 'young'
    
        
    >>> p1 = People('Dean',16)
    >>> p1.term_age = types.MethodType(fn_get_age,p1)
    >>> print (p1.term_age())
    young

    这个是python3.0的写法,如果是2.0的话呢我们就需要一个另外的一种写法:

    import types
    def fn_get_grade(self):
        if self.score >= 80:
            return 'A'
        if self.score >= 60:
            return 'B'
        return 'C'
    
    class Person(object):
        def __init__(self, name, score):
            self.name = name
            self.score = score
    
    p1 = Person('Bob', 90)
    p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
    print p1.get_grade()
    # => A
    p2 = Person('Alice', 65)
    print p2.get_grade()
    # ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
    # 因为p2实例并没有绑定get_grade

    主要的区别是我们的types。MethodType的使用的方法不一样,3.0的版本是需要两个参数,2.0的版本是需要三个参数。

    和属性类似,方法也分实例方法类方法

    通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count

    因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。

    class Person(object):
        count = 0
        @classmethod
        def how_many(cls):
            return cls.count
        def __init__(self, name):
            self.name = name
            Person.count = Person.count + 1
    
    print Person.how_many()
    p1 = Person('Bob')
    print Person.how_many()
  • 相关阅读:
    无root权限安装tmux
    mosquitto_pub和mosquitto_sub 命令参数说明
    安装Mosquitto学习MOTT协议
    Linux之prink原理
    JZ2440支持设备树(1)-添加设备树之后kernel的启动参数跟dts里面不一致
    Linux可以生产uImage
    Ubuntu18.04下make menuconfig缺少ncurses库
    如何打开kernel最开始的打印
    buildroot管理uboot+kernel+rootfs
    STM32L071CBTX操作ECC508
  • 原文地址:https://www.cnblogs.com/chang1203/p/5843999.html
Copyright © 2011-2022 走看看