super主要解决钻石继承(多继承)问题。
class Base(object):
def __init__(self):
print("Base init")
class Medium1(Base):
def __init__(self):
super(Medium1, self).__init__()
print("Medium1 init")
class Medium2(Base):
def __init__(self):
super(Medium2, self).__init__()
print("Medium2 init")
class Leaf(Medium1, Medium2):
def __init__(self): # 实例化时候调用,此处的self是空实例
super(Leaf, self).__init__()
# 获取self的类的mro列表,然后依次从mro列表中且在leaf类右侧的类的init方法,
# 找到对应的属性就返回,不在继续往下查找
print("Leaf init")
print(Leaf.mro())
'''
[<class '__main__.Leaf'>, <class '__main__.Medium1'>, <class '__main__.Medium2'>,
<class '__main__.Base'>, <class 'object'>]
'''
leaf = Leaf()
'''
Base init
Medium2 init
Medium1 init
Leaf init
'''
super(type, obj)
class Medium1(Base):
def __init__(self):
super(Medium1, self).__init__()
print("Medium1 init")
super(Leaf, self).__init__()
流程如下:
1、获取 self 所属类的mro,即[Leaf, Medium1, Medium2,Base]
;
2、从mro中Leaf右边的一个类开始,依次寻找__init__
函数。这里是从Medium1开始寻找一旦找到,就把找到的__init__
函数绑定到self对象,并返回。
3、从这个执行流程可以看到,如果我们不想调用Medium1的__init__
,而想要调用Medium2的__init__
,那么super应该写成:super(Medium1, self)__init__()
即可。
super(type, type2)
class Leaf(Medium1, Medium2):
def __new__(cls):
obj = super(Leaf, cls).__new__(cls)
print("Leaf new")
return obj
super(Leaf, cls).__new__(cls)
流程如下:
1、获取cls这个类的mro,即[Leaf, Medium1, Medium2, Base]
;
2、从mro中Leaf右边的一个类开始,依次寻找__new__
函数一旦找到,就返回“ 非绑定 ”的__new__
函数。
3、由于返回的是非绑定的函数对象,因此调用时不能省略函数的第一个参数。这也是这里调用__new__
时,需要传入参数cls的原因,同样的,如果我们想从某个mro的某个位置开始查找,只需要修改super的第一个参数就行。