python钻石继承

如果子类继承自两个单独的超类,而那两个超类又继承自同一个公共基类,那么就构成了钻石继承体系。这种继承体系很像竖立的菱形,也称作菱形继承。

class Base:
    def __init__(self, value):
        self.value = value


class One(Base):
    def __init__(self, value):
        Base.__init__(self, value)
        self.value *= 2


class Two(Base):
    def __init__(self, value):
        Base.__init__(self, value)
        self.value += 3


class Ways(One, Two):
    def __init__(self, value):
        One.__init__(self, value)
        Two.__init__(self, value)

foo = Ways(5)
print(foo.value)

8

我们认为它会输出13,但结果却是8,因为在调用第二个超类时,即Two.__init__,它会再次调用Base.__init__,从而导致self.value重新变成5.

解决这个问题的方式是使用super方法,根据方法解析顺序(MRO)以标准化的流程来安排超类之间的初始化顺序,它也能够保证钻石顶部的公共基类的__init__方法之运行一次。

class Base:
    def __init__(self, value):
        self.value = value


class One(Base):
    def __init__(self, value):
        super(One, self).__init__(value)
        self.value *= 2


class Two(Base):
    def __init__(self, value):
        super(Two, self).__init__(value)
        self.value += 3


class Ways(One, Two):
    def __init__(self, value):
        super(Ways, self).__init__(value)

foo = Ways(5)
print(foo.value)

16

这是怎么回事?为何和我们设想的刚好相反。应该先运行One.__init__,然后运行Two.__init__。但实际却不一样,程序的运行会与Ways的MRO顺序保持一致。调用Ways(5)时,它会调用One.__init__,One.__init__又调用Two.__init__,Two.__init__在调用Base.__init__。到达了钻石继承的顶端,所有的初始化方法会按照与刚才那些__init__相反的顺序操作。

class Base:
    def __init__(self, value):
        self.value = value


class One(Base):
    def __init__(self, value):
        super(One, self).__init__(value * 2)


class Two(Base):
    def __init__(self, value):
        super(Two, self).__init__(value + 3)


class Ways(One, Two):
    def __init__(self, value):
        super(Ways, self).__init__(value)

foo = Ways(5)
print(foo.value)

13
这样做问题就解决了。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值