Python的经典类和新式类的区别

新式类都从object继承,经典类不需要。

  • 新式类相同父类只执行一次构造函数,经典类重复执行多次。

其中:

  • 截止到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.x

1
2
3
4
5
6
7
8
class A:  
pass
class B:
pass
class C(B):
pass
class D(C,A):
pass

执行顺序为:D->C->B,->A

python3.x

1
2
3
4
5
6
7
8
class A(object):  
pass
class B(object):
pass
class C(object):
pass
class D(A,B,C):
pass

执行顺序为: D->A->B->C->Object


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- coding:utf-8 -*-    

class E:
#经典类
pass

class E1(object):
#新式类
pass

e = E()
print "经典类"
print e
print type(e)
print e.__class__

print "新式类"
e1 = E1()
print e1
print e1.__class__
print type(e1)

执行结果

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
2
3
4
5
6
7
8
9
10
11
class A(object):    
__slots__ = ('name', 'age')

class A1():
__slots__ = ('name', 'age')

a1 = A1()
a = A()

a1.name1 = "a1"
a.name1 = "a"

A是新式类添加了__slots__属性,所以只允许添加 name age,
A1经典类__slots__ 属性没用,直接回出错

  • 通常每一个实例都会有一个__dict__属性,用来记录实例中所有的属性和方法,也是通过这个字典,可以让实例绑定任意的属性

  • __slots__属性作用就是,当类C有比较少的变量,而且拥有__slots__属性时,

  • 类C的实例 就没有__dict__属性,而是把变量的值存在一个固定的地方。如果试图访问一个__slots__中没有的属性,实例就会报错。这样操作有什么好处呢?__slots__属性虽然令实例失去了绑定任意属性的便利,但是因为每一个实例没有__dict__属性,却能有效节省每一个实例的内存消耗,有利于生成小而精干的实例。