Python在2.2之后就有使用一种叫做new style class,即新式类
首先需要说明的是,在python3.X(包括3.0)中,新建类都自动生成为新式类,新式类成为默认值。
(如果不是为了兼容性考虑,建议使用最新版本的python解释环境,毕竟发展是朝向更加标准、清晰走的。)
新式类的定义也就是等同于与经典类的区别:
1. 第一个区别是在声明时有区别,得到的结果也有不同
# 在python2.7解释环境中
class A: pass #经典类
class B(object): pass #在2.X环境中,若声明为新式类需要直接继承object类
a = A()
b = B()
print a
print type(a)
print type(a.__class__)
print b
print type(b)
print type(b.__class__)
<__main__.A instance at 0x000001B34B1707B8>
__main__.A
<__main__.B object at 0x000001B34B170278>
# 在python 3.6解释环境中
class C:pass # 新式类为默认值,无需显式继承自object,等同于在python2.X中的语句: class C(object): pass
c = C()
print(c)
print(c.__class__)
print(type(c))
结果:
<__main__.C object at 0x000001B34B16B400>
经典类的多继承时,属性搜索顺序为:先深入继承树的左侧,再返回开始找右侧,也就是深度优先;
新式类的多继承时,属性搜索顺序为:先找最近超类(父类)从左至右,再深度搜索更高超类,也就是所谓的广度优先。
例:
# ptyhon 3.6解释环境中,新式类广度优先
class A: x = 1
class B(A): pass
class C(A): x = 3
class D(B,C): pass
d = D()
print(d.x)
结果:
>>> 3
属性的搜索过程:d --> D --> B --> C --> A,
而如果在经典类搜索模式中以上搜索过程就变为:d --> D --> B --> A --> C
# ptyhon 2.7解释环境中,新式类广度优先
class A: x = 1
class B(A): pass
class C(A): x = 3
class D(B,C): pass
d = D()
print(d.x)
结果:
>>> 1
在经典类中,有一个概念就是钻石搜索模式,所谓的钻石搜索模式就是经典类搜索模式,即上面提到的深度优先原则搜索模式,在看《python学习手册(第四版)》时有一点混乱,所以这里拿出来说一下。
3. 支持__slots__实例属性列表
__slots__中加入的属性是该类生成的实例能够访问和改变的唯一属性(包括从超类__slots__中获得的属性)
# python3.6解释环境,windows系统下
class D:
__slots__ = ['name','age']
d = D()
d.name = 'Dogg Snop'
print(d.name)
d.location = 'Tianjing'
print(d.location)
结果:
Dogg Snop
Traceback (most recent call last):
File "", line 1, in
d.location = 'Tianjing'
AttributeError: 'D' object has no attribute 'location'
如果属性没有在类的命名空间中使用__slots__指出,那么实例就无法再外部进行赋值使用(即添加新属性)
D.location = "Tianjing"
print(d.location)
结果:
Tianjing
这个也就是在实例中去掉了__dict__属性,才出现无法再实例中无法添加新属性,但是类名直接添加属性;如果想要让用户添加属性,但是又不想被滥用,则可以在__slots__中添加__dict__属性: __slots__ = [……, '__dict__'],这样用户就无法直接使用d.attrname = attrvalue,而必须使用d.__slots__.__dict__[attrname] = attrvalue,防止意外添加属性导致的属性错误和泛滥。
4. 在新式类中,添加了__getattribute__()方法
# Python3.X解释器中
class A:
def __getattribute__(self, *args, **kwargs):
print "A.__getattribute__"
a = A()
a.test
结果:
>>> A.__getattribute__
# Python 2.X解释器中
class B:
def __getattribute__(self, *args, **kwargs):
print "B.__getattribute__"
b = B()
b.test
Traceback (most recent call last):
File "", line 1, in
b.test
AttributeError: B instance has no attribute 'test'