Python超级方法和调用替代品 [英] Python super method and calling alternatives
问题描述
super(SuperClass,instance).method() args)
有什么不利的地方:
SuperClass.method(instance,args)
请考虑以下情况:
类A(对象):
def __init__ (self):
print('Running A .__ init__')
super(A,self).__ init __()
class B(A):
def __init __ :
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 ):
def __init __(self):
print('Running D .__ init__')
super(D,self).__ init __()
foo = D ()
所以类构成了一个所谓的继承菱形:
A
/ \
BC
\ /
D
运行代码会产生
.__ init__
运行B .__ init__
运行A .__ init__
C
的 __ init __
被跳过。原因是因为 B
的 __ init __
调用 A
' __ init __
。
super
的目的是解析继承菱形。如果取消注释
#super(B,self).__ init __()
和注释
A .__ init__ (self)
代码产生更可取的结果:
运行D .__ init__
运行B .__ init__
运行C .__ init__
运行A .__ init__
现在所有 __ init __
方法被调用。注意,在定义 B .__ init __
的时候,你可能会认为 super(B,self).__ init __
与调用 A .__ init __(self)
相同,但是你会错了。在上述情况下, super(B,self).__ init __()
实际调用 C .__ init __(self)
。
圣烟, B 对
C
并且 super(B,self)
知道调用 C
的 __ init __
?原因是因为 self .__ class __。mro()
包含 C
。换句话说, self
(或在上面, foo
)知道 C
。
请小心 - 这两个不可替代。
使用超级
有陷阱。在继承图中的所有类之间需要相当程度的协调。 (例如,它们必须对 __ init __
具有相同的调用签名,因为任何特定的 __ init __
其他 __ init __
super
可能调用next,或
else use ** kwargs
)此外,您必须一致使用 super
无处不在。跳过一次(如上例所示),并且击败 super
的整个目的。
查看更多陷阱的链接。
如果你完全控制你的类层次结构,或者你避免继承钻石,那么就不需要 super
。
I see everywhere examples that super-class methods should be called by:
super(SuperClass, instance).method(args)
Is there any disadvantage to doing:
SuperClass.method(instance, args)
Consider the following situation:
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 the code yields
Running D.__init__
Running B.__init__
Running 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.
The purpose of super
is to resolve inheritance diamonds. If you un-comment
# super(B,self).__init__()
and comment-out
A.__init__(self)
the code yields the more desireable result:
Running D.__init__
Running B.__init__
Running C.__init__
Running A.__init__
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)
.
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.
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.
If you have full control over your class hierarchy, or you avoid inheritance diamonds, then there is no need for super
.
这篇关于Python超级方法和调用替代品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!