python中类的全面分析(下)


3)数据属性
下面创建了一个Student的类,并且实现了这个类的初始化函数"__init__":

>>> class Student(object):
    count = 0
    books = []
    def __init__(self, name, age):
        self.name = name
        self.age = age

在上面的Student类中,count, books, name 和 age 都被称为类的数据属性,但是它们又分为类数据属性和实例数据属性。直接定义在类体中的属性叫类属性,而在类的方法中定义的属性叫实例属性。

首先看下面代码,展示了对类数据属性和实例数据属性的访问:
>>> Student.books.extend(['python', 'java'])
>>> print('Student book list:%s' % Student.books)
Student book list:['python', 'java']
>>> Student.hobbies = ['reading', 'jogging', 'swimming']
>>> print('Student hobby list:%s' % Student.hobbies)
Student hobby list:['reading', 'jogging', 'swimming']
>>> print(dir(Student))
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'books', 'count', 'hobbies']

>>> wilber = Student('Wilber', 28)
>>> print('%s is %d years old' % (wilber.name, wilber.age))
Wilber is 28 years old
>>> wilber.gender = 'male'
>>> print('%s is %s' % (wilber.name, wilber.gender))
Wilber is male

>>> wilber.books.append('C#')
>>> print(wilber.books)
['python', 'java', 'C#']

通过内建函数dir(),或者访问类的字典属性__dict__,这两种方式都可以查看类或者实例有哪些属性。对于类数据属性和实例数据属性,可以总结为:
1.类数据属性属于类本身,可以通过类名进行访问/修改;
2.类数据属性也可以被类的所有实例访问/修改;
3.在类定义之后,可以通过类名动态添加类数据属性,新增的类属性也被类和所有实例共有;
4.实例数据属性只能通过实例访问;
5.在实例生成后,还可以动态添加实例数据属性,但是这些实例数据属性只属于该实例;

再看下面的程序
>>> class Person:
    name = 'aaa'

    
>>> p1 = Person()
>>> p2 = Person()
>>> p1.name = 'bbb'
>>> print(p1.name)
bbb
>>> print(p2.name)
aaa
>>> print(Person.name)
aaa

上面程序中,p1.name="bbb"是实例调用了类变量,p1.name一开始是指向的类变量name="aaa",但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量。self.name不再引用Person的类变量name了。
>>> class Person:
    name = []

    
>>> p1 = Person()
>>> p2 = Person()
>>> p1.name.append(1)
>>> print(p1.name)
[1]
>>> print(p2.name)
[1]
>>> print(Person.name)
[1]

4)特殊的类属性
对于所有的类,都有一组特殊的属性:
类属性        含义
__name__    类的名字(字符串)
__doc__        类的文档字符串
__bases__    所有父类组成的元组
__dict__    类的属性组成的字典
__module__    类所属的模块
__class__    类对象的类型

5)类的继承
Python 是面向对象语言,支持类的继承(包括单重和多重继承),继承的语法如下:
class DerivedClass(BaseClass1, [BaseClass2...]): 
    <statement-1> 
    . 
    <statement-N>  
子类可以覆盖父类的方法,此时有两种方法来调用父类中的函数:
1.调用父类的未绑定的构造方法。在调用一个实例的方法时,该方法的self参数会被自动绑定到实例上(称为绑定方法)。但如果直接调用类的方法(比如A.init),那么就没有实例会被绑定。这样就可以自由的提供需要的self参数,这种方法称为未绑定(unbound)方法。大多数情况下是可以正常工作的,但是多重继承的时候可能会重复调用父类。
2.通过 super(cls, inst).method() 调用 MRO中下一个类的函数,这里有一个非常不错的解释,看完后对 super 应该就熟悉了。

未绑定(unbound)方法调用如下:
>>> class Base(object):
    def __init__(self):
        print('Base.__init__')


>>> class Derived(Base):
    def __init__(self):
        Base.__init__(self)
        print('Derived.__init__')

supper 调用如下:
>>> class Base(object):
    def __init__(self):
        print('Base.__init__')

        
>>> class Derived(Base):
    def __init__(self):
        super(Derived, self).__init__()
        print('Derived.__init__')

        
>>> class Derived_2(Derived):
    def __init__(self):
        super(Derived_2, self).__init__()
        print('Derived_2.__init__')


6)构造与析构
当我们调用 x = SomeClass() 的时候,第一个被调用的函数是 __new__ ,这个方法创建实例。接下来可以用 __init__ 来指明一个对象的初始化行为。当这个对象的生命周期结束的时候, __del__ 会被调用。

1.__new__(cls,[...]) 是对象实例化时第一个调用的方法,它只取下 cls 参数,并把其他参数传给init。
2.__init__(self,[...]) 为类的初始化方法。它获取任何传给构造器的参数(比如我们调用 x = SomeClass(10, ‘foo’) ,init 函数就会接到参数 10 和 ‘foo’) 。
3.__del__(self):new和init是对象的构造器, del则是对象的销毁器。它并非实现了语句 del x (因此该语句不等同于x.__del__()),而是定义当对象被回收时的行为。

猜你喜欢

转载自blog.csdn.net/zhaocen_1230/article/details/81198458