Python超级方法和调用替代品 [英] Python super method and calling alternatives

查看:108
本文介绍了Python超级方法和调用替代品的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆