问题描述
假设我有一个多继承场景:
Say I have a multiple inheritance scenario:
class A(object):
# code for A here
class B(object):
# code for B here
class C(A, B):
def __init__(self):
# What's the right code to write here to ensure
# A.__init__ and B.__init__ get called?
编写C
的__init__
有两种典型的方法:
There's two typical approaches to writing C
's __init__
:
- (旧式)
ParentClass.__init__(self)
- (新式)
super(DerivedClass, self).__init__()
但是,无论哪种情况,如果父类(A
和 B
)不要遵循相同的约定,那么代码将无法正常工作(有些可能会被遗漏,或者被多次调用).
However, in either case, if the parent classes (A
and B
) don't follow the same convention, then the code will not work correctly (some may be missed, or get called multiple times).
那么正确的方法又是什么呢?说保持一致,遵循其中之一"很容易,但是如果 A
或 B
来自 3rd 方库,那又如何?有没有一种方法可以确保所有父类构造函数都被调用(并且以正确的顺序,并且只调用一次)?
So what's the correct way again? It's easy to say "just be consistent, follow one or the other", but if A
or B
are from a 3rd party library, what then? Is there an approach that can ensure that all parent class constructors get called (and in the correct order, and only once)?
看看我的意思,如果我这样做:
to see what I mean, if I do:
class A(object):
def __init__(self):
print("Entering A")
super(A, self).__init__()
print("Leaving A")
class B(object):
def __init__(self):
print("Entering B")
super(B, self).__init__()
print("Leaving B")
class C(A, B):
def __init__(self):
print("Entering C")
A.__init__(self)
B.__init__(self)
print("Leaving C")
然后我得到:
Entering C
Entering A
Entering B
Leaving B
Leaving A
Entering B
Leaving B
Leaving C
注意 B
的 init 被调用了两次.如果我这样做:
Note that B
's init gets called twice. If I do:
class A(object):
def __init__(self):
print("Entering A")
print("Leaving A")
class B(object):
def __init__(self):
print("Entering B")
super(B, self).__init__()
print("Leaving B")
class C(A, B):
def __init__(self):
print("Entering C")
super(C, self).__init__()
print("Leaving C")
然后我得到:
Entering C
Entering A
Leaving A
Leaving C
请注意,B
的 init 永远不会被调用.所以看来,除非我知道/控制我从(A
和 B
)继承的类的初始化,否则我无法为我正在编写的类做出安全的选择(C
).
Note that B
's init never gets called. So it seems that unless I know/control the init's of the classes I inherit from (A
and B
) I cannot make a safe choice for the class I'm writing (C
).
推荐答案
两种方式都可以正常工作.使用 super()
的方法为子类带来了更大的灵活性.
Both ways work fine. The approach using super()
leads to greater flexibility for subclasses.
在直接调用方式中,C.__init__
可以同时调用A.__init__
和B.__init__
.
In the direct call approach, C.__init__
can call both A.__init__
and B.__init__
.
当使用super()
时,类需要设计为协作多重继承,其中C
调用super
,后者调用A
的代码也会调用 super
调用 B
的代码.见 http://rhettinger.wordpress.com/2011/05/26/super-thinked-super 了解更多关于 super
可以做什么的细节.
When using super()
, the classes need to be designed for cooperative multiple inheritance where C
calls super
, which invokes A
's code which will also call super
which invokes B
's code. See http://rhettinger.wordpress.com/2011/05/26/super-considered-super for more detail on what can be done with super
.
[稍后编辑的回答问题]
[Response question as later edited]
所以似乎除非我知道/控制我的类的初始化继承自 (A 和 B) 我无法为我所在的班级做出安全的选择写作(C).
引用的文章展示了如何通过在 A
和 B
周围添加包装类来处理这种情况.在标题为如何合并非合作班级"的部分中有一个已解决的示例.
The referenced article shows how to handle this situation by adding a wrapper class around A
and B
. There is a worked-out example in the section titled "How to Incorporate a Non-cooperative Class".
人们可能希望多重继承更简单,让您轻松组合 Car 和 Airplane 类以获得 FlyingCar,但实际情况是,单独设计的组件通常需要适配器或包装器才能像我们希望的那样无缝地组合在一起:-)
One might wish that multiple inheritance were easier, letting you effortlessly compose Car and Airplane classes to get a FlyingCar, but the reality is that separately designed components often need adapters or wrappers before fitting together as seamlessly as we would like :-)
另一个想法:如果您对使用多重继承组合功能不满意,您可以使用组合来完全控制在哪些情况下调用哪些方法.
One other thought: if you're unhappy with composing functionality using multiple inheritance, you can use composition for complete control over which methods get called on which occasions.
这篇关于使用多重继承调用父类 __init__,正确的方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!