使用super()、__init__() 和多重继承有点棘手。
在正常的流程中,每个方法都会调用super(),而仅从object继承的类会做一些额外的工作来确保该方法确实存在:它'看起来有点像这样:
>>> class Foo(object):
... def frob(self, arg):
... print "Foo.frob"
... if hasattr(super(Foo, self), 'frob'):
... super(Foo, self).frob(arg)
...
>>> class Bar(object):
... def frob(self, arg):
... print "Bar.frob"
... if hasattr(super(Bar, self), 'frob'):
... super(Bar, self).frob(arg)
...
>>> class Baz(Foo, Bar):
... def frob(self, arg):
... print "Baz.frob"
... super(Baz, self).frob(arg)
...
>>> b = Baz()
>>> b.frob(1)
Baz.frob
Foo.frob
Bar.frob
>>>
但是当你尝试在 object 实际拥有的方法上做类似的事情时,事情会变得有点冒险; object.__init__ 不带参数,因此使用它的唯一安全方法是不带参数调用super().__init__(),因为该调用可能由object.__init__ 处理。但它可能不由object.__init__ 处理,而是由继承图中其他位置的类处理。因此,任何类在多继承类层次结构中定义__init__必须准备好以无参数调用。
解决这个问题的一种方法是永远不要在__init__() 中使用参数。做最少的初始化,并依靠设置属性或使用其他方式在使用前配置新对象。不过,这很不愉快。
另一种方法是仅使用关键字参数,例如def __init__(self, **keywords):,并始终删除适用于给定构造函数的参数。这是一个基于希望的策略,您希望在控制权到达object.__init__ 之前消耗所有关键字。
第三种方法是为所有可多重继承的基定义一个超类,它本身以某种有用的方式定义了__init__,并且不调用super().__init__(object.__init__ 是否- 无论如何)。这意味着您可以确定始终最后调用此方法,并且您可以随心所欲地处理参数。