简体   繁体   English

super()和Parent类名之间有什么区别?

[英]What's the difference between super() and Parent class name?

Is there a difference between using super() and using the parent class name directly? 使用super()和直接使用父类名称有区别吗? For example: 例如:

class Parent:
    def __init__(self):
        print("In parent")
        self.__a=10

class Child(Parent):
    def __init__(self):
        super().__init__()     # using super()
        Parent.__init__(self)  # using Parent class name

c=Child()

Is there internally a difference between super().__init__() and Parent.__init__(self) ? 内部是否有super().__init__()Parent.__init__(self)之间的区别?

Not in this case . 不是在这种情况下 But in general , and especially when you use multiple inheritance , super() delegates to the next object in the Method Resolution Order (MRO) as is specified in the documentation : 总的来说 ,尤其是当您使用多重继承时super()委托方法解析顺序(MRO)中的下一个对象,文档中所指定:

super([type[, object-or-type]])

Return a proxy object that delegates method calls to a parent or sibling class of type. 返回将方法调用委托给父类或兄弟类类型的代理对象 This is useful for accessing inherited methods that have been overridden in a class. 这对于访问已在类中重写的继承方法很有用。 The search order is same as that used by getattr() except that the type itself is skipped. 搜索顺序与getattr()使用的搜索顺序相同,只是跳过了类型本身。

The __mro__ attribute of the type lists the method resolution search order used by both getattr() and super() . 类型__mro__属性列出了 getattr()super()使用的方法解析搜索顺序 The attribute is dynamic and can change whenever the inheritance hierarchy is updated. 该属性是动态的,并且可以在更新继承层次结构时更改。

(...) (......)

(copied, boldface added) (复制,粗体添加)

Say for instance you define classes like (borrowed from this question, where the MRO is discussed in more detail ): 比如说你定义了类(从这个问题中借用,更详细地讨论了MRO ):

class F:
    def __init__(self):
        print('F%s'%super().__init__)
        super().__init__()

class G: 
    def __init__(self):
        print('G%s'%super().__init__)
        super().__init__() 

class H: 
    def __init__(self):
        print('H%s'%super().__init__)
        super().__init__()

class E(G,H):
    def __init__(self):
        print('E%s'%super().__init__)
        super().__init__()

class D(E,F): 
    def __init__(self):
        print('D%s'%super().__init__)
        super().__init__() 

class C(E,G): 
    def __init__(self):
        print('C%s'%super().__init__)
        super().__init__()

class B(C,H): 
    def __init__(self):
        print('B%s'%super().__init__)
        super().__init__()

class A(D,B,E): 
    def __init__(self):
        print('A%s'%super().__init__)
        super().__init__()

Then the __mro__ of A is: 然后A__mro__是:

A.__mro__ == (A,D,B,C,E,G,H,F,object)

Now if we call A() , it prints: 现在如果我们调用A() ,它会打印:

A<bound method D.__init__ of <__main__.A object at 0x7efefd8645c0>>
D<bound method B.__init__ of <__main__.A object at 0x7efefd8645c0>>
B<bound method C.__init__ of <__main__.A object at 0x7efefd8645c0>>
C<bound method E.__init__ of <__main__.A object at 0x7efefd8645c0>>
E<bound method G.__init__ of <__main__.A object at 0x7efefd8645c0>>
G<bound method H.__init__ of <__main__.A object at 0x7efefd8645c0>>
H<bound method F.__init__ of <__main__.A object at 0x7efefd8645c0>>
F<method-wrapper '__init__' of A object at 0x7efefd8645c0>
<__main__.A object at 0x7efefd8645c0>

so it means that in the context of A and when trying to obtain __init__ that: 所以这意味着A的上下文中 ,当试图获得__init__

  • super().__init__ of A is D.__init__ ; super().__init__AD.__init__ ;
  • super().__init__ of D is B.__init__ ; D super().__init__B.__init__ ;
  • super().__init__ of B is C.__init__ ; B super().__init__C.__init__ ;
  • super().__init__ of C is E.__init__ ; C super().__init__E.__init__ ;
  • super().__init__ of E is G.__init__ ; E super().__init__G.__init__ ;
  • super().__init__ of G is H.__init__ ; G super().__init__H.__init__ ;
  • super().__init__ of H is F.__init__ ; H super().__init__F.__init__ ; and
  • super().__init__ of F is object.__init__ . F super().__init__object.__init__

Note thus that super() does not per se delegates to a parent . 因此请注意, super()本身并不代表父母 For instance the super() of D is B and B is not a superclass of D , so it really depends on the type of the object (not on the class). 例如, Dsuper()BB不是D的超类,所以它实际上取决于对象的类型 (不在类上)。

Now in case of D , the __mro__ is: 现在在D情况下, __mro__是:

D.__mro__ = (D,E,G,H,F,object)

If we construct a D however we get: 如果我们构建一个D我们得到:

D<bound method E.__init__ of <__main__.D object at 0x7efefd864630>>
E<bound method G.__init__ of <__main__.D object at 0x7efefd864630>>
G<bound method H.__init__ of <__main__.D object at 0x7efefd864630>>
H<bound method F.__init__ of <__main__.D object at 0x7efefd864630>>
F<method-wrapper '__init__' of D object at 0x7efefd864630>

So in the context of D it holds that: 因此,在D的背景下,它认为:

  • super().__init__ of D is E.__init__ ; D super().__init__E.__init__ ;
  • super().__init__ of E is G.__init__ ; E super().__init__G.__init__ ;
  • super().__init__ of G is H.__init__ ; G super().__init__H.__init__ ;
  • super().__init__ of H is F.__init__ ; H super().__init__F.__init__ ; and
  • super().__init__ of F is object.__init__ . F super().__init__object.__init__

So here the super() of D leads to E (for __init__ ) which is not the same in the context of A . 所以这里Dsuper()导致E (对于__init__ ,这A的上下文中不一样A

super().__init__(*args, **kwargs)   

Perceive you don't pass the "self" - it is inserted automatically. 感觉你没有通过“自我” - 它会自动插入。

super() was first designed in Python 2 to allow classes to be reused as mixins in a class hierarchy in a way that their immediate superclass may change: super()最初是在Python 2中设计的,允许类在类层次结构中作为mixin重用,其直接超类可能会更改:

Let's supose at some point in time your code is like: 让我们在某个时间点使用您的代码:

class A: pass
class B(A): 
    def __init__(self, *args, **kwargs):
          ...
          # Fixed call to A
          A.__init__(self, *args, **kwargs)

class C(A):
    def __init__(self, *args, **kwargs):
          ...
          # Fixed call to A
          A.__init__(self, *args, **kwargs)

class D(C, B): 
    pass

At this point, correct OOP code should execute C.__init__ which should chain the call to B.__init__ : but when the superclass name is hardcoded that does not happen - A 's __init__ would always come next. 在这一点上,正确的OOP代码应该执行C.__init__ ,它应该将调用链接到B.__init__ :但是当超类名称被硬编码时不会发生 - A__init__总是接下来。 And if you hardcode B.__init__ in C , you would prevent C from working without B , defeating the purpose of multiple inheritance. 如果你在C硬编码B.__init__ ,你会阻止C在没有B情况下工作,从而B.__init__多重继承的目的。

When you use super() instead, Python's perform the method search for the next parent class looking on the class's __mro__ attribute (mro = method resolution order. __mro__ is a concrete attribute attached to each Python class). 当您使用super() ,Python会执行方法搜索下一个查看类的__mro__属性的子类(mro =方法解析顺序__mro__是附加到每个Python类的具体属性)。 - So, if at some point in time class D above no longer inherits from B , the calls to super().__init__ in C will be automatically re-routed straight to A . - 因此,如果在某个时间点上面的D类不再继承自B ,则对C super().__init__的调用将自动重新路由到A

It is also worth noting that in Python 3 the parameterless form of super was introduced to ease its use - prior to that, one had to hardcode a reference to the own class and also insert self in the parameters. 值得注意的是,在Python 3中引入了无参数形式的super以简化其使用 - 在此之前,必须对自己的类进行硬编码并在参数中插入self This form is one of the few exceptions in Python that is hardcoded in the compiler itself - it do change things internally on methods when super (or __class__ ) is seen inside a method body (namely, it creates a __class__ variable pointing to the class itself which the super call uses) 这个表单是Python中为数不多的在编译器本身中进行硬编码的例外之一 - 当在方法体内看到super (或__class__ )时,它会在方法内部进行更改(即,它创建一个指向类本身的__class__变量) super电话使用的)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 通过超级调用父类与父类名称之间的区别? - Difference between invoking parent class via super vs the parent class name? 使用 super() 和使用 self 从父类调用方法有什么区别? - What is the difference between calling a method from parent class using super() and using self? 了解父 class init() 和 super.__init__ 之间的区别 - Understanding difference between parent class init() and super.__init__ 在从python对象继承的Class和从另一个用户定义的Class继承的Class上使用super()之间的区别是什么 - What's the difference between using super() on a Class inherited from python object and a Class inherited from another user-defined Class `super(...)`和`return super(...)`有什么区别? - What is the difference between `super(…)` and `return super(…)`? super()。method()和self.method()有什么区别 - What's the difference between super().method() and self.method() 在Django中,作为字段参数的verbose_name和Meta内部class中的verbose_name有什么区别? - In Django, what's the difference between verbose_name as a field parameter, and verbose_name in a Meta inner class? 通过类的名称访问类的属性与类方法有什么区别? - What's the difference between accessing a class' attribute via the class' name vs classmethod? 在Python中,“class name(object):”和“class name():”之间有什么区别? - In Python, what is the difference between “class name(object):” and “class name():” 属性和类方法有什么区别? - what's the difference between property and class method?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM