Python的经典类和新式类的区别
新式类都从object继承,经典类不需要。
- 新式类的MRO(method resolution order 基类搜索顺序)算法采用C3算法广度优先搜索,而旧式类的MRO算法是采用深度优先搜索,深度优先遍历和广度优先遍历的区别
- 新式类相同父类只执行一次构造函数,经典类重复执行多次。
其中:
截止到python2.1,只存在旧式类。旧式类中,类名和type是无关的:如果x是一个旧式类,那么
x.__class__
定义了x的类名,但是type(x)总是返回<type 'instance'>
。这反映了所有的旧式类的实例是通过一个单一的叫做instance的内建类型来实现的,这是它和类不同的地方。新式类是在python2.2为了统一类和实例引入的。一个新式类只能由用户自定义。如果x是一个新式类的实例,那么type(x)和
x.__class__
是一样的结果(尽管这不能得到保证,因为新式类的实例的__class__
方法是允许被用户覆盖的)。Python 2.x中默认都是经典类,只有显式继承了object才是新式类
Python 3.x中默认都是新式类,经典类被移除,不必显式的继承object
python2.x1
2
3
4
5
6
7
8class A:
pass
class B:
pass
class C(B):
pass
class D(C,A):
pass
执行顺序为:D->C->B,->A
python3.x1
2
3
4
5
6
7
8class A(object):
pass
class B(object):
pass
class C(object):
pass
class D(A,B,C):
pass
执行顺序为: D->A->B->C->Object
1 | # -*- coding:utf-8 -*- |
执行结果1
2
3
4
5
6
7
8
9经典类
<__main__.E instance at 0x0000000002250B08>
<type 'instance'>
__main__.E
新式类
<__main__.E1 object at 0x0000000002248710>
<class '__main__.E1'>
<class '__main__.E1'>
- 新式类增加了
__getattribute__
方法 - 新式类增加了
__slots__
内置属性, 可以把实例属性的种类锁定到__slots__
规定的范围之中。
1 | class A(object): |
A是新式类添加了__slots__
属性,所以只允许添加 name age,
A1经典类__slots__
属性没用,直接回出错
通常每一个实例都会有一个
__dict__
属性,用来记录实例中所有的属性和方法,也是通过这个字典,可以让实例绑定任意的属性而
__slots__
属性作用就是,当类C有比较少的变量,而且拥有__slots__
属性时,类C的实例 就没有
__dict__
属性,而是把变量的值存在一个固定的地方。如果试图访问一个__slots__
中没有的属性,实例就会报错。这样操作有什么好处呢?__slots__
属性虽然令实例失去了绑定任意属性的便利,但是因为每一个实例没有__dict__
属性,却能有效节省每一个实例的内存消耗,有利于生成小而精干的实例。