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

歡迎訪問 生活随笔!

生活随笔

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

python

python 构造函数继承_Python多重继承的异构构造器

發布時間:2025/3/12 python 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python 构造函数继承_Python多重继承的异构构造器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在Python里面,如果你使用上Qt,SQLAlchemy,Twisted之類各種大型類庫時候,有時候多重繼承Multiple Inheritance是個簡單的解決方法,但是多重繼承的復雜性總容易造成誤解和疑惑。

一般“常識”說,使用super訪問父類的屬性/方法,這種說法在多重繼承里面是不成立的,多重繼承的類并沒有父類的概念(There is no superclass in a MI world)。類似的博客在過去幾年被人寫了無數遍了,因為過去版本里面python官方文檔對super的解釋非常有限而且有誤導解釋,直到2.6以后的文檔,才詳細說明了super在單繼承和多繼承的兩種不同工作方式。當時苦逼的程序員甚至不得不去翻看Python源碼才搞清楚是什么回事。以致幾年來很多人對python的多重繼承保持懷疑態度。

Python多重繼承使用Method Resolution Order的動態算法來解決一個方法名的調用順序,mro其實說來簡單,就是一個深度優先的繼承列表,很易理解,但隨之來的是遇到互不相同的構造器__init__參數的問題。

Codepad運行結果:

class A(object):

def __init__(self, arg1):

print "init func in A, with arg1 '%s'" % arg1

super(A, self).__init__()

class B(object):

def __init__(self, arg1, arg2):

print "init func in B, with arg1'%s', arg2 '%s'" % (arg1, arg2)

super(B, self).__init__(arg1)

class C(B, A):

def __init__(self, arg1, arg2):

print "init func in C, with arg1'%s', arg2 '%s'" % (arg1, arg2)

super(C, self).__init__(arg1, arg2)

print C.__mro__

c = C("C's arg1", "C's arg2")

執行結果:

init func in C, with arg1'C's arg1', arg2 'C's arg2'

init func in B, with arg1'C's arg1', arg2 'C's arg2'

init func in A, with arg1 'C's arg1'

(, , , )

可見幾個類的構造器的執行順序正是mro列表的順序。重點是多重繼承的各個類的構造器__init__之所以能夠執行,是因為每個構造器里面都有一句super(),這個super完成mro列表中下一個類的構造器的調用。

這個事實聽起來似乎很自然,但看代碼,B的構造器還得必須知道A的構造器的參數?B需要知道自己將會被C同時繼承A,并且調用A的構造?!!很荒謬,但不幸的這是mro的特點。代碼是可以這么寫,但不應該,為另一個不知道什么時候會被一起繼承的類特地地寫代碼,跟面對對象設計的解耦原則相違背。How

在mro方式的基礎上,這個問題是不可能有效解決的,只能避免。概括起來大概有這么 兩種方式。

1.使用傳統類的方式,顯式調用被繼承類的構造器,避開super的mro自動化工作。

Codepad 看運行效果:

class A(object):

def __init__(self, arg1):

print "init func in A, with arg1 '%s'" % arg1

class B(object):

def __init__(self, arg1, arg2):

print "init func in B, with arg1'%s', arg2 '%s'" % (arg1, arg2)

class C(A, B):

def __init__(self, arg1, arg2):

print "init func in C, with arg1'%s', arg2 '%s'" % (arg1, arg2)

#super(C, self).__init__(arg1) #這兩行

A.__init__(self, arg1) #等價

B.__init__(self, arg1, arg2)

print C.__mro__

c = C("C's arg1", "C's arg2")

注意 C繼承A,B的順序已經改變。

要排除一個容易產生的誤解。Python文檔里面的super有個很顯著的Note:super() only works for new-style classes. super只適用于新類。但新類并不必須使用super。

直接調用被繼承類的__init__作為unbound方法調用,需要指定一個實例,如self作為參數,依次調用各個被繼承類。缺點是若果這幾個被繼承類也在構造方法里面使用這樣調用了同一個上級被繼承類,會出現“爺爺類”的構造方法被調用多次的情況。

如果一定使用super,要注意繼承列表的順序。super(TYPE, self).method調用的是mro列表中第一個,也即繼承列表第一個類的方法。

PyQt里面的類內部一般(未細究)都使用__init__的方式來初始化代碼,因而很多PyQt的例子代碼都是使用QtGui.QMainWindow.__init__(self)這樣的代碼來初始化。當然在單繼承時候和super的寫法是等價的,但最好使用統一的原則:

一個簡單好記的原則:

如果”被繼承類”都使用__init__,”繼承類”就使用__init__來初始化;

如果”被繼承類”都使用super,”繼承類”就使用super來初始化;

2.使用Composition / Association Pattern的設計模式(即’Is-A’轉換成’Has-A’)來實現相同功能,避免多重繼承。

這個方法聽起來未免有點讓人不快(破壞了原有設計思維),但實際上很可能這是更好的方式,更清晰的代碼,尤其是要繼承的類里面混合了使用super,__init__兩種初始化方式的時候。;

玩蛇網文章,轉載請注明出處和文章網址:https://www.iplaypy.com/jinjie/jj5808.html

相關文章 Recommend

總結

以上是生活随笔為你收集整理的python 构造函数继承_Python多重继承的异构构造器的全部內容,希望文章能夠幫你解決所遇到的問題。

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