Python之super函数

在面向对象编程时,继承是必不可少的,而定义时往往需要在子类的一些操作时(如初始化等),除了处理自己的部分外,还需要调用基类的对应同名函数。在Python中有两种方法,一种是直接使用父类的类名,另一种是使用super函数,这两者间有什么区别呢?

其实对于正常的单继承来讲,两者之间是没有区别的,其区别在于多继承的菱形继承情况中,相当于C++中的虚继承场景。考虑如下示例代码,先看一下不使用super函数的场景:

class Base():
    def __init__(self):
        print('Base')

class A(Base):
    def __init__(self):
        print('A')
        Base.__init__(self)

class B(Base):
    def __init__(self):
        print('B')
        Base.__init__(self)

class C(A, B):
    def __init__(self):
        print('C')
        A.__init__(self)
        B.__init__(self)

c= C()
其结果显示如下:

>>> 
C
A
Base
B
Base
可以看到其中的Base的初始化函数执行了2次,再换做super函数,代码如下

class Base():
    def __init__(self):
        print('Base')

class A(Base):
    def __init__(self):
        print('A')
        super(A, self).__init__()

class B(Base):
    def __init__(self):
        print('B')
        super(B, self).__init__()

class C(A, B):
    def __init__(self):
        print('C')
        super(C, self).__init__()

c= C()
其结果如下,可见Base的初始化函数只执行了一次。

>>> 
C
A
B
Base
Python中的属性查找与类继承密切相关,其会依次在当前对象属性以及其父类中递归查找,其各个父类的顺序就相当重要。Python中采用一种MRO计算方法来对继承结构中的类进行排序(新类),通过属性__mro__可以查看每个类的继承顺序。

print(C.__mro__)
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)
而super函数也即是针对每个类的__mro__中查找对应的类的下一个类,其执行结果 相当于如下代码:
class C(A, B):
    def __init__(self):
        print('C')
        #super(C, self).__init__()
        mro = self.__class__.__mro__
        mro[mro.index(C)+1].__init__(self)
因此在实际使用尽量使用super,特别注意不可两者方式混用。


PS:MRO算法

1)依据继承关系形成多条继承链;

2)从左到右依次选择链首的类,从中找出第一个满足如下条件的类:其不出现在其他链中,或者处于其他链的链头,将其加入到__mro__中,并在所有链中删除

3)然后重新执行过程2,直到类都已经加入到__mro__中;

针对示例中的类,其执行顺序如下:

1)形成两条链 [C, A, Base], [C, B, Base]

2)依次选择C, A, B, Base,最后形成__mro__



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值