为什么不调用所有基类构造函数?

时间:2016-10-09 03:31:25

标签: python python-2.7

在Python 2.7.10中

class OneMixin(object):
    def __init__(self):
        # super(OneMixin, self).__init__()
        print "one mixin"

class TwoMixin(object):
    def __init__(self):
        # super(TwoMixin, self).__init__()
        print "two mixin"

class Account(OneMixin, TwoMixin):
    def __init__(self):
        super(Account, self).__init__()
        print "account"

Account.mro()是:[<class 'Account'>, <class 'OneMixin'>, <class 'TwoMixin'>, <type 'object'>]

虽然每个班级都列在MRO中,但是#34;两个混音&#34;没有打印。

如果我取消注释OneMixin和TwoMixin中的超级调用,则MRO完全相同,但是&#34;两个混合&#34; IS打印。

为何与众不同?我希望MRO中的所有东西都能被调用。

2 个答案:

答案 0 :(得分:1)

这是因为super用于将调用委托给类型的父类或兄弟类。 Python documentation对第二个用例进行了以下描述:

  

第二个用例是在动态执行环境中支持协作多重继承。此用例是Python独有的,在静态编译语言或仅支持单继承的语言中找不到。这使得实现“菱形图”成为可能,其中多个基类实现相同的方法。好的设计要求此方法在每种情况下都具有相同的调用签名(因为调用的顺序是在运行时确定的,因为该顺序适应类层次结构中的更改,并且因为该顺序可以包括在运行时之前未知的兄弟类)。

如果您从super删除了OneMixin来电,则无法将此次来电委托给MRO中的下一个类型。

答案 1 :(得分:1)

原因是您重写了父类的__init__方法。无论您的__init__方法是什么,方法解析顺序都是相同的。

super的工作方式是将它传递给方法解析顺序中的下一个类。通过在OneMixin中注释掉该行,您可以打破链条。 super专为合作继承而设计。

此外,__init__也不是真正的类构造函数。如果您将其视为其他语言的构造函数,这可能会让您失望。