Python - 这是调用超类'方法的更好方法吗?

kak*_*eys 17 python oop class

我一直在使用:

SuperClass.__init__(self, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

我的理由是,它明确地显示了使用哪个超类,特别是在多重继承的情况下.

但是,我遇到的其他代码使用

super(MyClass, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

代替.

在用于以下情况时,这可能会变得暧昧:

class MyClass(SuperClass1, SuperClass2):
    def __init__(self, *args, **kwargs):
        super(MyClass, self).__init__(*args, **kwargs) #which SuperClass is being used?
Run Code Online (Sandbox Code Playgroud)

我想知道为什么这种呼叫形式被广泛采用?有什么优势吗?

aar*_*ing 21

super对现代(新风格)类优先的原因是它允许合作多重继承.这是一个例子.

>>> class Foo(object):
...     def display(self):
...         print "In Foo"
... 
>>> class Foo2(Foo):
...     def display(self):
...         print "In Foo2"
...         super(Foo2, self).display()
...         print "Back in Foo2"
... 
>>> class Bar(Foo):
...     def display(self):
...         print "In Bar"
...         super(Bar, self).display()
...         print "Back in Bar"
... 
>>> class FooBar(Foo2, Bar):
...     pass
... 
>>> FooBar().display()
In Foo2
In Bar
In Foo
Back in Bar
Back in Foo2
>>> class BarFoo(Bar, Foo2):
...     pass
... 
>>> BarFoo().display()
In Bar
In Foo2
In Foo
Back in Foo2
Back in Bar
Run Code Online (Sandbox Code Playgroud)

请注意,我没有做任何事情来改变display超类上的方法,但是display通过改变我安排超类的顺序,我在子类上得到了不同的方法.BarFooFooBar有不同的方法.这是因为他们有不同的方法解决方案订单

>>> BarFoo.__mro__
(<class '__main__.BarFoo'>, <class '__main__.Bar'>, <class '__main__.Foo2'>, <class '__main__.Foo'>, <type 'object'>)
>>> FooBar.__mro__
(<class '__main__.FooBar'>, <class '__main__.Foo2'>, <class '__main__.Bar'>, <class '__main__.Foo'>, <type 'object'>)
Run Code Online (Sandbox Code Playgroud)

这意味着super为每个被调用的子类解析为一个不同的类.这允许每个重写方法改变正在进行的一小部分,并且只要他们愿意,仍然允许每个其他超类对方法调用做出贡献.好好玩.


use*_*312 6

对于继承自的新样式类object,super使用.

__mro__所述的(方法解析顺序)属性类型列出了所使用的方法的分辨率搜索顺序super.

>>> class X(object):
    pass

>>> class Y(object):
    pass

>>> class Z(X, Y):
    pass

>>> Z.__mro__
(<class '__main__.Z'>, <class '__main__.X'>, <class '__main__.Y'>, <type 'object'>)
Run Code Online (Sandbox Code Playgroud)

这指定Z.排序既然是Z(X, Y),X首先在层次中.如果是的话Z(Y, X),Y会先于结束X.

对于旧式类,SuperClass.__init__(self, *args, **kwargs)使用.

更新:

关于哪个SuperClass正在使用的问题.

>>> class First(object):
    pass

>>> class Second(object):
    def __init__(self, *args, **kwargs):
        print 'Second __init__ called'

>>> class MInherit(First, Second):
    def __init__(self):
        super(MInherit, self).__init__()

>>> i = MInherit()
Second __init__ called
Run Code Online (Sandbox Code Playgroud)

首先,First将检查它是否有__init__,因为First在MRO中是第一个.因为在这种情况下'First'没有__init__,所以Second被称为.如果有一个__init__进入First,只会被称为.