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

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

问题描述

我到处都看到应该通过以下方式调用超类方法的示例:

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).

天啊,BC一无所知,但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屋!

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