1. python2和python3中定义类的形式不同
python3中只有只有新式类
class A(object): # python3中定义新式类
class A: # python3中定义新式类(省略object)
python2中有经典类和新式类区别:
class A(object): # python2中定义新式类
class A: # python2中定义经典类
新式类和经典类只要区别在继承搜索顺序上,
-- 经典类,搜索深度优先,先深入继承树左侧查找,然后返回,开始右侧查找
-- 新式类,搜索广度优先,先水平查找,再向上查找
python2-新式类:super(类, self)
必须显示的申明,python3-默认自己时可省略而使用super()
python2-新式类例子
class A(object):
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
super(B,self).__init__()
class C(A):
def __init__(self):
print("C")
super(C,self).__init__()
class D(B, C):
def __init__(self):
print("D")
super(D,self).__init__()
d = D()
print(D.mro())
新式类——继承树查找——广度模式,D —> B —> C —> A
>>> d = D()
D
B
C
A
>>> print(D.mro())
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]
python2经典类
class A:
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
super(B,self).__init__()
class C(A):
def __init__(self):
print("C")
super(C,self).__init__()
class D(B, C):
def __init__(self):
print("D")
super(D,self).__init__()
结果:经典类没有mro属性,也就不能用super(class, self)
来调用
>>> d = D()
D
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
TypeError: super() argument 1 must be type, not classobj
>>> D.mro()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: class D has no attribute 'mro'
2. 类继承的两种方式
** 显示地调用方法:类.__init__(self)
** 通过 super()
调用
2.1 单继承下,两者结果一样
class A(object):
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
A.__init__(self)
b = B()
class B(A):
def __init__(self):
print("B")
super().__init__()
b = B()
两者方法的结果一样:
B
A
B
A
2.2 多继承下
显示调用方法在多继承模式下存在的问题:父类被调用不止一次
class A(object):
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
A.__init__(self)
class C(A):
def __init__(self):
print("C")
A.__init__(self)
class D(B, C):
def __init__(self):
print("D")
B.__init__(self)
C.__init__(self)
d = D()
结果 A
类被调用了两次
D
B
A
C
A
使用 super()
方法,相同的类只被调用一次,python2 中使用 super(class, self).__init__()
,而python3 中默认可不写,直接使用super().__init__()
class A(object):
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
super().__init__()
class C(A):
def __init__(self):
print("C")
super().__init__()
class D(B, C):
def __init__(self):
print("D")
super().__init__()
d = D()
结果如下:
D
B
C
A
这里需要注意的一点,如果部分类使用super()
方法,会出现继承不全等问题,如下:
其中B、C类显示继承,导致结果出问题
class A(object):
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
A.__init__(self)
class C(A):
def __init__(self):
print("C")
A.__init__(self)
class D(B, C):
def __init__(self):
print("D")
super().__init__()
d = D()
结果:
D
B
A
tips: ① 不要混合使用类.__init__(self)
和 super()
,② 尽量使用 super()
方法
3. super调用顺序 —— mro
3.1 查看类的继承顺序
mro(method resolution order):表示类继承体系中的成员顺序。查看方法:类.mro()
回到前面那个例子:
class A(object):
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
A.__init__(self)
class C(A):
def __init__(self):
print("C")
A.__init__(self)
class D(B, C):
def __init__(self):
print("D")
super().__init__()
print(D.mro())
结果表示对于D类的继承顺序为: D —> B —> C —> A,这与上述的结果相符。
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
3.2 super(cls, self)类指定,默认为当前类
class A(object):
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
super().__init__()
class C(A):
def __init__(self):
print("C")
super().__init__()
使用默认类此时 super().__init__()
== super(D, self).__init__()
class D(B, C):
def __init__(self):
print("D")
super(D,self).__init__()
d = D()
print(D.mro())
结果如下:
D
B
C
A
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
修改默认为类为B,
class D(B, C):
def __init__(self):
print("D")
super(B, self).__init__()
d = D()
print(D.mro())
结果如下:发现B不见了。 为什么?
-
这里super(B, self)表示:
-- self这里指D自身,也即将D的继承顺序 [D, B, C, A, object] 传递给super()
-- B表示从B的下一顺序开始,这里从 C —> A —> object
-- 将第一个找到的__init__
函数绑定到self对象,并返回
D
C
A
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]