传统父类方法调用
# super.py
class SuperClass(object):
def act(self):
print("Super Class act method ...")
class SubClass(SuperClass):
def act(self):
SuperClass.act(self) # 显式地调用父类方法
print("SubClass act method ...")
if __name__ == '__main__':
sub = SubClass()
sub.act()
>>> python super.py
super()方法只能在py3.x中使用,py2.x必须要指明类名
# super.py
class SuperClass(object):
def act(self):
print("Super Class act method ...")
class SubClass(SuperClass):
def act(self):
super().act()
# super(SubClass,self).act() # py2.x 调用父类,过于复杂,这个可以正常执行
print("SubClass act method ...")
if __name__ == '__main__':
sub = SubClass()
sub.act()
>>> python super.py
super在多继承中的使用
# super.py
class A(object):
def act(self):
print("call A act method ....")
class B(object):
def act(self):
print("call B act method ....")
class C(B,A): # 搜索的顺序会从B开始搜索,B存在act方法则调用并返回,不再继续搜索
def act(self):
super().act()
if __name__ == '__main__':
c = C()
c.act()
>>> python super.py
super不支持运算符操作,如super()[index]
# super.py
class E(object):
def __getitem__(self, item):
print("call E __getitem__ method ...")
class F(E):
def __getitem__(self, item):
print('call F __getitem__ method ..')
E.__getitem__(self, item)
super().__getitem__(item)
super()[item] # 不支持运算符操作,'super' object is not subscriptable
def test_opr():
f = F()
f[2]
if __name__ == '__main__':
test_opr()
>>> python super.py
在运行时可以改变类的继承树
# super.py
class X(object):
def m1(self):
print("call X method")
class Y(object):
def m1(self):
print("call Y method")
class Z(X):
def m1(self):
super().m1()
def test_z():
z = Z()
z.m1()
print("change Z class base for Y ....")
Z.__bases__=(Y,)
z.m1()
if __name__ == '__main__':
test_z()
>>> python super.py
能够在多继承中按照广度优先的继承树搜索关系链来有序地调用与父类相同名称的方法,且在每个子类拥有super的都会执行父类方法
# super.py
class IA(object):
def __init__(self):
print("call IA init ...") # 基类IA没有super(),没有意义
class IB(IA):
def __init__(self):
print("call IB init ....")
super().__init__()
class IC(IA):
def __init__(self):
print("call IC init ....")
super().__init__()
class ID(IC,IB):
def __init__(self):
print("call ID init ...")
super().__init__()
def test_ID():
d = ID()
print(ID.mro())
if __name__ == '__main__':
test_ID()
>>> python super.py
纠正一下,上面不是深度优先而是广度优先
在父类没有使用super()情况下,在子类中将使用类的继承树搜索方式来匹配父类方法,找到并返回调用,不再继续往下搜索
# super.py
class P1(object):
def __init__(self):
print("call P1 init ...")
class P2(object):
def __init__(self):
print("call P2 init ...")
# 以下两种方式等价
class S(P2,P1):
pass # 默认调用父类的构造方法,如果有定义的话并且子类没有调用super()将不会调用父类方法
class S(P2,P1):
def __init__(self):
super().__init__()
if __name__ == '__main__':
S()
>>> python super.py
子类的继承树最近的父类如果没有使用super(),则调用链停止,如果使用super()将以广度优先的方式进行遍历,通过mro()查看调用链
# super.py 用上述的IA,IB,IC,ID做示例
...
class IC(IA):
def __init__(self):
print("call IC init ....")
# super().__init__() # 调用链停止
...
>>> python super.py
子类多继承中,按上述所说的,如果父类存在super()调用,将以广度优先地处理方式进行搜索,比如
# super.py
class P1(object):
def __init__(self):
print("call P1 init ...")
super().__init__()
class P2(object):
def __init__(self):
print("call P2 init ...")
super().__init__()
class S(P2,P1):
# 最先搜索到的父类是P2,如果P2有使用super()来调用,那么就会以MRO的方式来搜索并继续往下调用,否则将停止调用
pass
def test_s():
s = S()
S.mro()
if __name__ == '__main__':
test_s()
>>> python super.py
在多继承中,最后的一个父类的顶层基类对应的super()将断开关系链,因为MRO的继承树最右边是object对象,不会继续往下调用
super()在多继承多个方法中的使用
# super.py
class MixSuperA(object):
def m1(self):
print("call mix super class A m1 method ...")
class MixSuperB(object):
def m2(self):
print("call mix super class B m2 method ...")
class SubClassA(MixSuperA):
def m2(self):
print("call sub class A m2 method ...")
class SubClassD(MixSuperA,MixSuperB):
def m1(self):
print("call sub class D m1 method ...")
super().m2() # 以MRO的搜索方式遍历
super().m1() # 以MRO的搜索方式遍历
if __name__ == '__main__':
d = SubClassD()
d.m1()
>>> python super.py
super调用的参数约束
# super.py
class Person(object):
def __init__(self,name,age):
print("call person init ...")
self.__name = name
self.__age = age
class Student(Person):
def __init__(self,age):
print("call Student init ...")
super().__init__("keithl",age) # 这里的super()使用MRO方式进行搜索,对应是Son,而Son只提供一个参数age的传递
class Son(Person):
def __init__(self,age):
print("call son init ...")
super().__init__("keithl",age)
class Me(Student,Son):
pass
if __name__ == '__main__':
Me(27)
>>> python super.py
# super.py
...
class Student(Person):
def __init__(self,name,age):
print("call Student init ...")
super().__init__(name,age)
class Son(Person):
def __init__(self,name,age):
print("call son init ...")
super().__init__(name,age)
...
>>> python super.py
...
class Student(Person):
pass # Student不做定义
class Son(Person):
def __init__(self,name,age):
print("call son init ...")
super().__init__(name,age)
...
>>> python super.py