[super][继承][面向对象][构造函数][多重继承]

本文探讨了Python中的super()内置函数在构造函数中的应用,对比了手动调用父类构造函数的两种方式。同时,文章深入讨论了三角继承和菱形继承带来的问题,特别是方法解析顺序(MRO)不一致的报错原因,并提出了通过避免直接多重继承来解决此类问题的建议。
摘要由CSDN通过智能技术生成

super()内置函数

父类的构造函数必须手动调用, 调用方式有2种:
1. MyParentClass.__init__(xxx)
2. super(MyClass, self).__init__(xxx)

区别在于: 1比较直观, 在涉及多重继承时, 可以手动控制父类构造函数的调用顺序, 需要手动为每个父类调用一次构造函数; 2比较灵活, 动态查找父类, 在涉及多重继承时, 会自动调用各个直接父类的构造函数;

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

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

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

class AA(object):
    def __init__(self):
        super(AA, self).__init__()
        print '__init__ AA'

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

d = D()
# 自动调用所以直接父类的构造函数
#__init__ AA
#__init__ A
#__init__ D

class BB(A):
    def __init__(self):
        print '__init__ BB'

class CC(BB):
    def __init__(self):
        super(CC, self).__init__()
        print '__init__ CC'

cc = CC()
# super()只会查找直接父类, 不会递归查找, 所以, 因为BB没有调动super, 所以A的构造函数就被调用
#__init__ BB
#__init__ CC

c = C()
# 当前类和父类都调用了super, 所以才能保证继承链上的所有构造函数都被调用
#__init__ A
#__init__ B
#__init__ C

三角继承

# 直接报错
class A:
    pass

class B(A):
    pass

class C(B, A):
    pass

c = C()
#TypeError: Error when calling the metaclass bases
    #Cannot create a consistent method resolution
#order (MRO) for bases B, A

报错原因

C继承A和B, 同时B也继承A, 对C来说, B和A是它的2个直接父类, 所以C在进行方法查找时, A和B具有相同的优先级, 但是这时候问题就来了:
1. 如果先从A再B, 那么B会覆盖A的方法(当然了, 这是我们所期望的, 因为B是A子类, 子类覆盖父类, 是理所当然的)
2. 如果先从B再A, 那么A会覆盖B的方法(出错了吧! 父类方法怎么可以覆盖子类方法呢!)

以上2种情况均可能出现, 这导致了方法解析顺序(MRO)不一致

解决方法

既然B继承A, 那么B已经包含了A的全部内容, 所以直接继承B就可以了, 没有必要继承A了:

class C(B):
    pass

万事大吉!

菱形继承

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

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

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

class D(B, C):
    def __init__(self):
        super(D, self).__init__()
        print '__init__ D'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值