使用多重继承调用父类__init__,这是正确的方法吗? [英] Calling parent class __init__ with multiple inheritance, what's the right way?
问题描述
假设我有一个多重继承方案:
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
' s __ init __
:
There's two typical approaches to writing C
's __init__
:
- (旧式)
ParentClass .__ init __(self)
- (更新式)
super(DerivedClass,self).__ init __()
- (old-style)
ParentClass.__init__(self)
- (newer-style)
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
来自第三方图书馆,那么呢?有没有一种方法可以确保所有父类构造函数被调用(并且以正确的顺序,只有一次)?
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/超级考虑超级,详细了解超级
可以做些什么。
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]
所以看起来除非我知道/控制类的初始化I
继承自(A)和B)我不能为上课做出安全的选择我是
写作(C)。
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).
参考文章通过在 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".
有人可能希望多重继承更容易,让你毫不费力地撰写汽车和飞机类可以获得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__,这是正确的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!