簡體   English   中英

super()和Parent類名之間有什么區別?

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

使用super()和直接使用父類名稱有區別嗎? 例如:

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

內部是否有super().__init__()Parent.__init__(self)之間的區別?

不是在這種情況下 總的來說 ,尤其是當您使用多重繼承時super()委托方法解析順序(MRO)中的下一個對象,文檔中所指定:

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

返回將方法調用委托給父類或兄弟類類型的代理對象 這對於訪問已在類中重寫的繼承方法很有用。 搜索順序與getattr()使用的搜索順序相同,只是跳過了類型本身。

類型__mro__屬性列出了 getattr()super()使用的方法解析搜索順序 該屬性是動態的,並且可以在更新繼承層次結構時更改。

(......)

(復制,粗體添加)

比如說你定義了類(從這個問題中借用,更詳細地討論了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__()

然后A__mro__是:

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

現在如果我們調用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>

所以這意味着A的上下文中 ,當試圖獲得__init__

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

因此請注意, super()本身並不代表父母 例如, Dsuper()BB不是D的超類,所以它實際上取決於對象的類型 (不在類上)。

現在在D情況下, __mro__是:

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

如果我們構建一個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>

因此,在D的背景下,它認為:

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

所以這里Dsuper()導致E (對於__init__ ,這A的上下文中不一樣A

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

感覺你沒有通過“自我” - 它會自動插入。

super()最初是在Python 2中設計的,允許類在類層次結構中作為mixin重用,其直接超類可能會更改:

讓我們在某個時間點使用您的代碼:

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

在這一點上,正確的OOP代碼應該執行C.__init__ ,它應該將調用鏈接到B.__init__ :但是當超類名稱被硬編碼時不會發生 - A__init__總是接下來。 如果你在C硬編碼B.__init__ ,你會阻止C在沒有B情況下工作,從而B.__init__多重繼承的目的。

當您使用super() ,Python會執行方法搜索下一個查看類的__mro__屬性的子類(mro =方法解析順序__mro__是附加到每個Python類的具體屬性)。 - 因此,如果在某個時間點上面的D類不再繼承自B ,則對C super().__init__的調用將自動重新路由到A

值得注意的是,在Python 3中引入了無參數形式的super以簡化其使用 - 在此之前,必須對自己的類進行硬編碼並在參數中插入self 這個表單是Python中為數不多的在編譯器本身中進行硬編碼的例外之一 - 當在方法體內看到super (或__class__ )時,它會在方法內部進行更改(即,它創建一個指向類本身的__class__變量) super電話使用的)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM