多重继承:只有1个父进程

时间:2013-11-18 12:37:21

标签: python python-2.7 initialization multiple-inheritance

我无法弄清楚为什么在下面的代码中只初始化了一个父构造函数:

class Base(object):
    def __init__(self):
        print "Base::Base():"


class BaseWArgs(object):
    def __init__(self, arg):
        print "BaseWArgs::BaseWArgs(%s):" % arg


class Composite(Base, BaseWArgs):
    def __init__(self):
        super(Composite,self).__init__()

在这种情况下,只调用Base。 init ()。如果我切换继承参数的顺序,则只初始化whatever-stand-first类:

class Composite(BaseWArgs, Base):
    def __init__(self):
        super(Composite,self).__init__('myArg')

如何通过一次通话初始化双方父母?这不应该是super()的责任吗?

EDIT 我认为我的用例是多重继承的特例。我想使用defaultdict作为基本类型创建一个项目,但是从第三种类型继承一些额外的功能。

from collections import defaultdict

class Base(object):
    def __init__(self):
        print "Base::Base():"
        super(Base,self).__init__()
        self.val = 'hello world'

class Item(defaultdict, Base):
    def __init__(self):
        super(Item,self).__init__(int)

>>> Item()
defaultdict(<type 'int'>, {})

>>> Item().val
Traceback (most recent call last):
  File "<pyshell#77>", line 1, in <module>
    Item().val
AttributeError: 'Item' object has no attribute 'val'

Base::Base()迷失在哪里?为什么Base未初始化?

1 个答案:

答案 0 :(得分:3)

Base.__init__BaseWArgs.__init__都没有实现对super().__init__的调用,因此显然只会调用rmo中的第一个调用。您必须让所有初始化程序都遵守协议才能使用它。

此外,当Base首先出现在mro中并且没有采取任何争论时,这仍然会失败。 &#34;协作&#34;超级调用要求您的方法签名兼容。以下代码会按预期委派调用:

class Base(object):
    def __init__(self):
        print "Base::Base():"
        super(Base, self).__init__()

class BaseWArgs(object):
    def __init__(self, arg):
        print "BaseWArgs::BaseWArgs(%s):" % arg
        super(BaseWArgs, self).__init__()


class Composite(BaseWArgs, Base):
    def __init__(self):
        super(Composite,self).__init__("foo")

c = Composite()

编辑:wrt /你的具体用例,似乎defaultdict没有自己进行super调用,所以除非它是基类中的最后一个,否则调用链将停在那里(好吧,它停在那里,但如果它持续下去则不会有问题。)

因此,您可以选择让自己的Base层次结构初始化程序与defaultdict的初始化程序兼容,并将defaultdict作为最后一个基类,或者明确地调用defaultdict的初始值设定项,然后调用Base初始值设定项,即:

class Base(object):
    def __init__(self):
        print "Base__init__():"
        super(Base, self).__init__()

class Sub(Base):
    def __init__(self):
        print "Sub.__init__():"
        super(Sub, self).__init__()
        self.foo = "bar"


class MyClass(defaultdict, Sub):
    def __init__(self):
        defaultdict.__init__(self, int)
        Sub.__init__(self)