super函数

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的第一个参数就行。

猜你喜欢

转载自www.cnblogs.com/fqh202/p/9383522.html