使用不同的参数在python中调用超类构造函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18006310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calling superclass constructors in python with different arguments
提问by Alexander Gruber
class A():
def __init__( self, x, y):
self.x = x
self.y = y
class B():
def __init__( self, z=0):
self.z = z
class AB(A,B):
def __init__( self, x, y, z=0):
?
How can I make the constructor of AB call the constructors for A and B with the proper arguments?
如何让 AB 的构造函数使用正确的参数调用 A 和 B 的构造函数?
I've tried
我试过了
class AB(A,B):
def __init__( self, x, y, z=0):
A.__init__(x,y)
B.__init__(z)
but this gives me an error.
但这给了我一个错误。
采纳答案by user2357112 supports Monica
You didn't pass self
.
你没有通过self
。
class AB(A, B):
def __init__(self, x, y, z=0):
A.__init__(self, x, y)
B.__init__(self, z)
Note that if this inheritance hierarchy gets more complicated, you'll run into problems with constructors not executing or getting reexecuted. Look into super
(and the problemswith super
), and don't forget to inherit from object
if you're on 2.x and your class doesn't inherit from anything else.
请注意,如果此继承层次结构变得更加复杂,您将遇到构造函数不执行或重新执行的问题。查看super
(以及 )的问题,如果您使用的是 2.x 并且您的类没有从其他任何东西继承super
,请不要忘记继承object
。
回答by ovgolovin
Other answers suggested adding self
to the first parameter.
其他答案建议添加self
到第一个参数。
But usually invocations of __init__
in parent classes are made by super
.
但通常__init__
在父类中的调用是由super
.
Consider this example:
考虑这个例子:
class A(object):
def __init__(self, x):
print('__init__ is called in A')
self.x = x
class B(object):
def __init__(self, *args, **kwargs):
print('__init__ is called in B')
super(B, self).__init__(*args, **kwargs)
class AB(B, A):
def __init__(self, *args, **kwargs):
print('__init__ is called in AB')
super(AB, self).__init__(*args, **kwargs)
AB
class contains an order in which constructors and initializators should be called:
AB
类包含调用构造函数和初始化器的顺序:
>>> AB.__mro__
(<class '__main__.AB'>, <class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
See, that first AB
's __init__
is invoked, then B
's, then A
's, and then object
's.
看,第一个AB
's__init__
被调用,然后是B
's,然后是A
's,然后是object
's。
Let's check:
让我们检查:
>>> ab = AB(1)
__init__ is called in AB
__init__ is called in B
__init__ is called in A
But these calls through this chain are made by super
. When we type super(AB, self)
, it means: find then next class after AB
in __mro__
chain of self
.
但是通过这个链的这些调用是由super
. 当我们输入 时super(AB, self)
,它的意思是:AB
在 的__mro__
链中找到然后下一个类self
。
Then we should invoke super
in B
, looking for the next class in the chain after B
: super(B, self)
.
然后我们应该调用super
in B
,在B
:之后寻找链中的下一个类super(B, self)
。
It's important to use super
and not call manually A.__init__(self,...)
, etc., as it may lead to problems later. Read this for more info.
使用super
而不是手动调用A.__init__(self,...)
等很重要,因为它可能会导致以后出现问题。阅读本文了解更多信息。
So, if you stick with super
, then there is a problem. __init__
methods in your classes expect different parameters. And you can't know for sure the order in which super
will be invoking methods in these classes. The order is determined by C3 algorithmat the time of class creation. In subclasses another classes may get in-between of the call chain. So you can't have different parameters in __init__
, as in this case you will have always to consider all inheritance chain to understand how __init__
methods will be called.
所以,如果你坚持super
,那么就有问题了。__init__
类中的方法需要不同的参数。并且您无法确定super
在这些类中调用方法的顺序。顺序由类创建时的C3算法决定。在子类中,另一个类可能会介于调用链之间。所以你不能在 中使用不同的参数__init__
,因为在这种情况下,你必须始终考虑所有继承链以了解如何__init__
调用方法。
For example, consider adding C(A)
and D(B)
classes and CD
subclass of them. Then A
will no longer be invoked after B
, but after C
.
例如,考虑增加C(A)
和D(B)
阶级和CD
他们的子类。thenA
将不再被调用 after B
,而是 after C
。
class A(object):
def __init__(self, *args, **kwargs):
print('__init__ is called in A')
super(A, self).__init__(*args, **kwargs)
class B(object):
def __init__(self, *args, **kwargs):
print('__init__ is called in B')
super(B, self).__init__(*args, **kwargs)
class AB(B,A):
def __init__(self, *args, **kwargs):
print('__init__ is called in AB')
super(AB, self).__init__(*args, **kwargs)
class C(A):
def __init__(self, *args, **kwargs):
print('__init__ is called in C')
super(C, self).__init__(*args, **kwargs)
class D(B):
def __init__(self, *args, **kwargs):
print('__init__ is called in D')
super(D, self).__init__(*args, **kwargs)
class CD(D,C):
def __init__(self, *args, **kwargs):
print('__init__ is called in CD')
super(CD, self).__init__(*args, **kwargs)
class ABCD(CD,AB):
def __init__(self, *args, **kwargs):
print('__init__ is called in ABCD')
super(ABCD, self).__init__(*args, **kwargs)
>>> abcd = ABCD()
__init__ is called in ABCD
__init__ is called in CD
__init__ is called in D
__init__ is called in AB
__init__ is called in B
__init__ is called in C
__init__ is called in A
So I think it's a good idea to think about using delegation
instead of inheritance here.
所以我认为delegation
在这里考虑使用而不是继承是个好主意。
class AB(object):
def __init__(self, x, y, z=0):
self.a = A(x,y)
self.b = B(z)
So, you just create a
and b
instances of A
and B
classes inside AB
object. And then may use them as you need through methods by referring to self.a
and self.b
.
所以,你只需要创建a
和b
实例A
和B
内部类AB
对象。然后可以通过引用self.a
和 的方法根据需要使用它们self.b
。
To use or not delegation depends on your case which is not clear from your question. But it may be an option to consider.
使用或不使用委托取决于您的情况,这从您的问题中不清楚。但这可能是一个可以考虑的选择。