Python 超级方法和调用替代方法 [英] Python super method and calling alternatives
问题描述
我到处都看到应该通过以下方式调用超类方法的示例:
I see everywhere examples that super-class methods should be called by:
super(SuperClass, instance).method(args)
这样做有什么缺点吗:
SuperClass.method(instance, args)
推荐答案
考虑以下情况:
class A(object):
def __init__(self):
print('Running A.__init__')
super(A,self).__init__()
class B(A):
def __init__(self):
print('Running B.__init__')
# super(B,self).__init__()
A.__init__(self)
class C(A):
def __init__(self):
print('Running C.__init__')
super(C,self).__init__()
class D(B,C):
def __init__(self):
print('Running D.__init__')
super(D,self).__init__()
foo=D()
所以这些类形成了所谓的继承菱形:
So the classes form a so-called inheritance diamond:
A
/
B C
/
D
运行代码收益
Running D.__init__
Running B.__init__
Running A.__init__
这很糟糕,因为 C
的 __init__
被跳过了.这是因为B
的__init__
直接调用了A
的__init__
.
That's bad because C
's __init__
is skipped. The reason for that is because B
's __init__
calls A
's __init__
directly.
super
的目的是解决继承钻石.如果你取消评论
The purpose of super
is to resolve inheritance diamonds. If you un-comment
# super(B,self).__init__()
并注释掉
A.__init__(self)
代码产生了更理想的结果:
the code yields the more desireable result:
Running D.__init__
Running B.__init__
Running C.__init__
Running A.__init__
现在所有 __init__
方法都被调用了.请注意,在定义 B.__init__
时,您可能认为 super(B,self).__init__()
与调用相同A.__init__(self)
,但你错了.在上述情况下,super(B,self).__init__()
实际上调用了C.__init__(self)
.
Now all the __init__
methods get called. Notice that at the time you define B.__init__
you might think that super(B,self).__init__()
is the same as calling A.__init__(self)
, but you'd be wrong. In the above situation, super(B,self).__init__()
actually calls C.__init__(self)
.
天啊,B
对C
一无所知,但super(B,self)
知道调用C
代码>的__init__
?原因是self.__class__.mro()
包含C
.换句话说,self
(或上面的foo
)知道C
.
Holy smokes, B
knows nothing about C
, and yet super(B,self)
knows to call C
's __init__
? The reason is because self.__class__.mro()
contains C
. In other words, self
(or in the above, foo
) knows about C
.
所以要小心——两者不可替代.它们可以产生截然不同的结果.
So be careful -- the two are not fungible. They can yield vastly different results.
使用super
有陷阱.这需要相当程度的协调在继承图中的所有类之间.(例如,它们必须对 __init__
具有相同的调用签名,因为任何特定的 __init__
都不知道其他哪个 __init__
super
可能会调用 next,或者否则 使用 **kwargs
.) 此外,您必须始终一致地使用 super
.跳过一次(如上面的例子),你就失去了 super
的全部目的.查看链接了解更多陷阱.
Using super
has pitfalls. It takes a considerable level of coordination between all the classes in the inheritance diagram. (They must, for example, either have the same call signature for __init__
, since any particular __init__
would not know which other __init__
super
might call next, or
else use **kwargs
.) Furthermore, you must be consistent about using super
everywhere. Skip it once (as in the above example) and you defeat the entire purpose of super
.
See the link for more pitfalls.
如果你可以完全控制你的类层次结构,或者你避免了继承钻石,那么就不需要 super
.
If you have full control over your class hierarchy, or you avoid inheritance diamonds, then there is no need for super
.
这篇关于Python 超级方法和调用替代方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!