日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

pythonsuper_用__init __()方法理解Python super()

發布時間:2025/4/5 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pythonsuper_用__init __()方法理解Python super() 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我想了解一下 super()

我們使用的原因super是,可能使用協作多重繼承的子類將在方法解析順序(MRO)中調用正確的下一個父類函數。

在Python 3中,我們可以像這樣調用它:class ChildB(Base):

def __init__(self):

super().__init__()

在Python 2中,我們需要像這樣使用它:super(ChildB, self).__init__()

沒有超級,您使用多重繼承的能力有限:Base.__init__(self) # Avoid this.

我在下面進一步解釋。“這段代碼實際上有什么區別?:”class ChildA(Base):

def __init__(self):

Base.__init__(self)class ChildB(Base):

def __init__(self):

super(ChildB, self).__init__()

# super().__init__() # you can call super like this in Python 3!

這段代碼的主要區別在于你在__init__with中獲得了一個間接層super,它使用當前類來確定__init__要在MRO中查找的下一個類。

我在規范問題的答案中說明了這種差異,如何在Python中使用'super'?,它演示了依賴注入和協作多重繼承。

如果Python沒有 super

這里的代碼實際上非常等同于super(如何在C中實現,減去一些檢查和回退行為,并轉換為Python):class ChildB(Base):

def __init__(self):

mro = type(self).mro() # Get the Method Resolution Order.

check_next = mro.index(ChildB) + 1 # Start looking after *this* class.

while check_next < len(mro):

next_class = mro[check_next]

if '__init__' in next_class.__dict__:

next_class.__init__(self)

break

check_next += 1

寫得更像本機Python:class ChildB(Base):

def __init__(self):

mro = type(self).mro()

for next_class in mro[mro.index(ChildB) + 1:]: # slice to end

if hasattr(next_class, '__init__'):

next_class.__init__(self)

break

如果我們沒有該super對象,我們必須在任何地方編寫此手動代碼(或重新創建它!)以確保我們在方法解析順序中調用正確的下一個方法!

超級如何在沒有明確告知調用方法的哪個類和實例的情況下在Python 3中執行此操作?

它獲取調用堆棧幀,并找到類(隱式存儲為本地自由變量,__class__使調用函數成為類的閉包)和該函數的第一個參數,該參數應該是通知它的實例或類要使用的方法解決順序(MRO)。

因為它需要MRO的第一個參數,所以使用super靜態方法是不可能的。

對其他答案的批評:使用super()可以避免顯式引用基類,這可能很好。。但主要優勢在于多重繼承,可以發生各種有趣的事情。如果您還沒有,請參閱super上的標準文檔。

這是相當浪漫的,并沒有告訴我們太多,但重點super是不要避免編寫父類。重點是確保調用方法解析順序(MRO)中的下一個方法。這在多重繼承中變得很重要。

我會在這里解釋一下。class Base(object):

def __init__(self):

print("Base init'ed")class ChildA(Base):

def __init__(self):

print("ChildA init'ed")

Base.__init__(self)class ChildB(Base):

def __init__(self):

print("ChildB init'ed")

super(ChildB, self).__init__()

讓我們創建一個我們希望在Child之后調用的依賴項:class UserDependency(Base):

def __init__(self):

print("UserDependency init'ed")

super(UserDependency, self).__init__()

現在記住,ChildB使用超級,ChildA不是:class UserA(ChildA, UserDependency):

def __init__(self):

print("UserA init'ed")

super(UserA, self).__init__()class UserB(ChildB, UserDependency):

def __init__(self):

print("UserB init'ed")

super(UserB, self).__init__()

并且UserA不調用UserDependency方法:>>> UserA()UserA init'ed

ChildA init'edBase init'ed

<__main__.UserA object at 0x0000000003403BA8>

但是UserB,因為ChildB使用super,確實!:>>> UserB()UserB init'ed

ChildB init'edUserDependency init'ed

Base init'ed<__main__.UserB object at 0x0000000003403438>

對另一個答案的批評

在任何情況下都不應該執行以下操作,這是另一個答案所暗示的,因為當您繼承ChildB時肯定會出錯:super(self.__class__, self).__init__() # Don't do this. Ever.

(這個答案并不聰明或特別有趣,但盡管評論中有直接的批評和超過17個downvotes,但回答者堅持提出建議,直到一位善良的編輯解決了他的問題。)

說明:那個回答建議像這樣調用super:super(self.__class__, self).__init__()

這是完全錯誤的。super讓我們在子類中查找MRO中的下一個父級(請參閱本答案的第一部分)。如果你告訴super我們在子實例的方法中,那么它將在行中查找下一個方法(可能是這個)導致遞歸,可能導致邏輯失敗(在回答者的例子中,它確實)或者RuntimeError當遞歸深度時超過了。>>> class Polygon(object):... def __init__(self, id):... self.id = id...>>> class Rectangle(Polygon):...

def __init__(self, id, width, height):... super(self.__class__, self).__init__(id)...

self.shape = (width, height)...>>> class Square(Rectangle):... pass...>>> Square('a', 10, 10)Traceback (most recent call last):

File "", line 1, in

File "", line 3, in __init__TypeError: __init__() missing 2 required positional arguments: 'width' and 'height'

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的pythonsuper_用__init __()方法理解Python super()的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。