super()和直接调用超类之间的区别 [英] Difference between super() and calling superclass directly

查看:78
本文介绍了super()和直接调用超类之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Python 2.7和3中,我使用以下方法调用超类的函数:

class C(B):
    def __init__(self):
        B.__init__(self)

我看到也可以用super(B, self).__init__()和python3 super().__init__()替换B.__init__(self).

以这种方式进行操作是否有优点或缺点?至少对我来说直接从B调用它更有意义,但是也许有充分的理由只能在使用元类时使用super()(我通常会避免).

解决方案

对于单继承,super()只是引用基本类型的一种更简单的方法.这样,您可以使代码更易于维护,例如,如果您想更改基本类型的名称.当您在任何地方都使用super时,只需在class行中进行更改.

真正的好处是多重继承.使用super时,单个调用不仅会自动调用 all 基本类型的方法(以正确的继承顺序),而且还会确保每个方法仅被调用一次. /p>

这实际上允许类型具有钻石属性,例如您只有一个基本类型A,并且有两个类型BC都从A派生.然后,您有一个D类型,它同时从BC继承(也隐式地从A继承-两次).如果您现在明确地调用基本类型的方法,则最终将两次调用A的方法.但是使用super,它只会调用一次:

class A (object):
    def __init__ (self):
        super().__init__()
        print('A')

class B (A):
    def __init__ (self):
        super().__init__()
        print('B')

class C (A):
    def __init__ (self):
        super().__init__()
        print('C')

class D (C, B):
    def __init__ (self):
        super().__init__()
        print('D')

现在实例化D时,将获得以下输出:

>>> D()
A
B
C
D
<__main__.D object at 0x000000000371DD30>

现在,让我们通过手动调用基本类型的方法来重新做一遍:

class A2 (object):
    def __init__ (self):
        print('A2')

class B2 (A2):
    def __init__ (self):
        A2.__init__(self)
        print('B2')

class C2 (A2):
    def __init__ (self):
        A2.__init__(self)
        print('C2')

class D2 (C2, B2):
    def __init__ (self):
        B2.__init__(self)
        C2.__init__(self)
        print('D2')

这是输出:

>>> D2()
A2
B2
A2
C2
D2
<__main__.D2 object at 0x0000000003734E48>

如您所见,A2发生两次.这通常不是您想要的.当您手动调用使用super的基本类型之一的方法时,它甚至变得更加混乱.因此,相反,您应该只使用super()来确保一切正常,而且也不必担心太多.

In Python 2.7 and 3, I use the following method to call a super-class's function:

class C(B):
    def __init__(self):
        B.__init__(self)

I see it's also possible to replace B.__init__(self) with super(B, self).__init__() and in python3 super().__init__().

Are there any advantages or disadvantages to doing this either way? It makes more sense to call it from B directly for me at least, but maybe there's a good reason where super() can only be used when using metaclasses (which I generally avoid).

解决方案

For single inheritance, super() is just a fancier way to refer to the base type. That way, you make the code more maintainable, for example in case you want to change the base type’s name. When you are using super everywhere, you just need to change it in the class line.

The real benefit comes with multiple inheritance though. When using super, a single call will not only automatically call the method of all base types (in the correct inheritance order), but it will also make sure that each method is only called once.

This essentially allows types to have a diamond property, e.g. you have a single base type A, and two types B and C which both derive from A. And then you have a type D which inherits from both B and C (making it implicitely inherit from A too—twice). If you call the base types’ methods explicitely now, you will end up calling A’s method twice. But using super, it will only call it once:

class A (object):
    def __init__ (self):
        super().__init__()
        print('A')

class B (A):
    def __init__ (self):
        super().__init__()
        print('B')

class C (A):
    def __init__ (self):
        super().__init__()
        print('C')

class D (C, B):
    def __init__ (self):
        super().__init__()
        print('D')

When we now instantiate D, we get the following output:

>>> D()
A
B
C
D
<__main__.D object at 0x000000000371DD30>

Now, let’s do all that again with manually calling the base type’s method:

class A2 (object):
    def __init__ (self):
        print('A2')

class B2 (A2):
    def __init__ (self):
        A2.__init__(self)
        print('B2')

class C2 (A2):
    def __init__ (self):
        A2.__init__(self)
        print('C2')

class D2 (C2, B2):
    def __init__ (self):
        B2.__init__(self)
        C2.__init__(self)
        print('D2')

And this is the output:

>>> D2()
A2
B2
A2
C2
D2
<__main__.D2 object at 0x0000000003734E48>

As you can see, A2 occurs twice. This is usually not what you want. It gets even messier when you manually call method of one of your base types that uses super. So instead, you should just use super() to make sure everything works, and also so you don’t have to worry about it too much.

这篇关于super()和直接调用超类之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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