當前位置:首頁 » 編程語言 » python多重繼承

python多重繼承

發布時間: 2022-08-02 21:18:25

1. python的多重繼承問題

樓上的回答的很正確,簡單來說:在對類D進行實例化的時候,你依次對類C和類A進行了初始化,結果就會以後初始化的B為准了

實際上在子類里並不需要去初始化父類,你在實例化子類的同時,繼承自父類的對象都會被創建

classA(object):
def__init__(self):
self.a=1

classB(A):
def__init__(self):
self.a=2
self.b=2
classC(B,A):
pass

>>> c = C()

>>> c.a

>>> 2

另外補充一下。父類為新式類的情況下,繼承順序是有影響的。繼承順序上,經典類是深度優先,新式類是廣度優先,兩種混用的話,分分鍾就暈乎了。可以去多做做實驗,好好了解。

2. Python有哪些技術上的優點比其他語言好在哪兒

Python有哪些技術上的優點


1. 面向對象和函數式

從根本上講,Python是一種面向對象的語言。它的類模型支持多態、運算符重載和多重繼承等高級概念,並且以Python特有的簡潔的語法和類型為背景,OOP十分易於使用。事實上,即使你不懂這些術語,仍會發現學習Python比學習其他OOP語言要容易得多。

除了作為一種強大的代碼組織和重用手段以外,Python的OOP本質使它成為其他面向對象系統語言的理想腳本工具。例如,通過適當的粘接代碼,Python程序可以對C++、Java和C#的類進行子類的定製。

OOP只是Python的一個選擇而已,這一點非常重要。即使不能立馬成為一個面向對象高手,但你同樣可以繼續深入學習。就像C++一樣,Python既支持面向對象編程也支持面向過程編程的模式。如果條件允許,其面向對象的工具可以立即派上用場。這對策略開發模式十分有用,該模式常用於軟體開發的設計階段。

除了最初的過程式(語句為基礎)和面向對象(類為基礎)的編程範式,Python在最近幾年內置了對函數式編程的支持——一個多數情況下包括生成器、推導、閉包、映射、裝飾器、匿名lambda函數和第一類函數對象的集合。這是對其本身OOP工具的補充和替代。

2. 免費

Python的使用和分發是完全免費的。就像其他的開源軟體一樣,例如,Tcl、Perl、Linux和Apache。你可以從Internet上免費獲得Python的源代碼。你可以不受限制地復制Python,或將其嵌入你的系統或者隨產品一起發布。實際上,如果你願意的話,甚至可以銷售它的源代碼。

但請別誤會:「免費」並不代表「沒有支持」。恰恰相反,Python的在線社區對用戶需求的響應和商業軟體一樣快。而且,由於Python完全開放源代碼,提高了開發者的實力,並產生了一個很大的專家團隊。

盡管研究或改變一種程序語言的實現並不是對每一個人來說都那麼有趣,但是當你知道如果需要的話可以做到這些,該是多麼的令人欣慰。你不需要去依賴商業廠商的智慧,因為最終的文檔和終極的凈土(源碼)任憑你的使用。

Python的開發是由社區驅動的,是Internet大范圍的協同合作努力的結果。Python語言的改變必須遵循一套規范而有約束力的程序(稱作PEP流程),並需要經過規范的測試系統進行徹底檢查。正是這樣才使得Python相對於其他語言和系統可以保守地持續改進。

盡管Python 2.X和Python 3.X版本之間的分裂有力並蓄意地破壞了這項傳統,但通常它仍然體現在Python的這兩個系列內部。

3. Python繼承中有兩個基類方法重名的問題。在線求解答~~~

1:在DerivedClass2
中,執行init
用了2個函數
BaseClass1.__init__(self)
BaseClass2.__init__(self)
所以
self.name
最後是
'BaseClass2_Name'
2:
調用class3.getname()
根據python多重繼承規則,從左到右,深度優先,調用的是BaseClass1的getname方法。
因此輸出這個結果。

4. python中super為什麼能解決多重繼承問題

1. super 並不是一個函數,是一個類名,形如 super(B, self) 事實上調用了 super 類的初始化函數,產生了一個 super 對象;

2. super 類的初始化函數並沒有做什麼特殊的操作,只是簡單記錄了類類型和具體實例;
3. super(B, self).func 的調用並不是用於調用當前類的父類的 func 函數;
4. Python 的多繼承類是通過 mro 的方式來保證各個父類的函數被逐一調用,而且保證每個父類函數只調用一次(如果每個類都使用 super);

5. 混用 super 類和非綁定的函數是一個危險行為,這可能導致應該調用的父類函數沒有調用或者一個父類函數被調用多次。
6. 用 super,遇到修改父類的名字時等情況

5. python 多重繼承,繼承的幾個父類都需要傳遞參數,怎麼在子類計算出父類傳遞的參數總和呢

運行你的代碼:出錯位置: c = C()

出錯結果:TypeError: __init__() missing 1 required positional argument: ' num1 '

先來看你的程序__main()__部分:a = A(2) 和 b = B(5) 這是類A和類B的一個實例。在python中實例變數是用於每個實例的唯一數據,這就說明你這里的傳遞參數2或者是5隻能用在實例化的 a 或者是 b 下才有作用。 那麼重點看c = C( ) ,c是類對象C的實例化,c 只能用自身實例變數才有用,因此前面的實例 a 下的變數 num1=2 和 實例 b 下的變數 num1=5對實例c是無用的。所以,出錯結果很明顯了缺少傳遞的位置參數了。這為什麼提示缺少1個位置參數呢?下面為你簡單講解一下吧。你也可以用內置方法__mro__() :查看方法或者屬性的調用路徑——print(類名.__mro__)

類C是多繼承類A和類B的,多繼承(不存在super()重寫方法下),類C的實例化c是怎麼工作的——對於實例c調用方法或屬性過程是這樣的:查找當前類C中是否存在,然後在多個父類中按照從左往右順序查找(類A中先查找,類B中後查找),只要在這個過程中找到就退出了,後面的就不再查找了。

好吧,給你分析一下你程序的過程:類A和類B中都有__init__()同一個方法,方法相同那首先就查找唄——先查找類C(沒有對__init__()進行修改,那就是跳過了),然後再去類A查找,好嘛這就找到了__init__(self, num1),找到了就退出了。所以這樣一看對類C進行實例化就需要傳遞一個參數給num1就夠了。你也可以交換繼承位置class C(B, A),這樣就是類C實例化需要傳遞一個參數給num2就夠了。這樣過程就清晰了。

好第三個問題來了:你類C中有兩個參數呀num1和num2,而實例化又僅需要一個參數就夠了,這樣就肯定會產生問題了。

不信你試試給c = C(2)產生錯誤:AttributeError: 'C' object has no attribute 'num2'

解決方法1:既然沒有屬性num2就在類C中刪掉就是了,然後c = C(2)就可以運行成功了。

解決方案2:類變數用於類的所有實例共享的屬性和方法。因此,要想共用這兩個變數num1和num2,就得讓搜索的時候不要進到類A和類B中前提下,將它們變成對應的類變數就可以了。第一個前提很好實現:在類C下 定義:def __init__(self) : pass 第二個條件也比較好實現:將類A或類B的 __init__(self, num) : X.num = num X為對應的類名。(說明:self表示類實例化對象,即self.num 表示實例變數;X表示類對象,則X.num表示類變數),這樣就可以共享類A和類B的變數了。

classA:
def__init__(self,num1):
A.num1=num1


classB:
def__init__(self,num2):
B.num2=num2


classC(A,B):

def__init__(self):
pass

defnum_sum(self):
returnself.num2+self.num1


if__name__=='__main__':
a=A(2)
b=B(5)
c=C()
print(c.num_sum())

6. python的簡單問題

要把代碼發現來才知道,以下是常見的錯誤下面終於要講到當你用到更多的Python的功能(數據類型,函數,模塊,類等等)時可能碰到的問題了。由於篇幅有限,這里盡量精簡,尤其是對一些高級的概念。要想了解更多的細節,敬請閱讀Learning Python, 2nd Edition的逗小貼士地以及逗Gotchas地章節。 打開文件的調用不使用模塊搜索路徑當你在Python中調用open()來訪問一個外部的文件時,Python不會使用模塊搜索路徑來定位這個目標文件。它會使用你提供的絕對路徑,或者假定這個文件是在當前工作目錄中。模塊搜索路徑僅僅為模塊載入服務的。不同的類型對應的方法也不同列表的方法是不能用在字元串上的,反之亦然。通常情況下,方法的調用是和數據類型有關的,但是內部函數通常在很多類型上都可以使用。舉個例子來說,列表的reverse方法僅僅對列表有用,但是len函數對任何具有長度的對象都適用不能直接改變不可變數據類型記住你沒法直接的改變一個不可變的對象(例如,元組,字元串): T = (1, 2, 3) T[2] = 4 # 錯誤 用切片,聯接等構建一個新的對象,並根據需求將原來變數的值賦給它。因為Python會自動回收沒有用的內存,因此這沒有看起來那麼浪費: T = T[:2] + (4,) # 沒問題了: T 變成了 (1, 2, 4) 使用簡單的for循環而不是while或者range 當你要從左到右遍歷一個有序的對象的所有元素時,用簡單的for循環(例如,for x in seq:)相比於基於while-或者range-的計數循環而言會更容易寫,通常運行起來也更快。除非你一定需要,盡量避免在一個for循環里使用range:讓Python來替你解決標號的問題。在下面的例子中三個循環結構都沒有問題,但是第一個通常來說更好;在Python里,簡單至上。 S = "lumberjack" for c in S: print c # 最簡單 for i in range(len(S)): print S[i] # 太多了 i = 0 # 太多了 while i len(S): print S[i]; i += 1 不要試圖從那些會改變對象的函數得到結果諸如像方法list.append()和list.sort()一類的直接改變操作會改變一個對象,但不會將它們改變的對象返回出來(它們會返回None);正確的做法是直接調用它們而不要將結果賦值。經常會看見初學者會寫諸如此類的代碼: mylist = mylist.append(X) 目的是要得到append的結果,但是事實上這樣做會將None賦值給mylist,而不是改變後的列表。更加特別的一個例子是想通過用排序後的鍵值來遍歷一個字典里的各個元素,請看下面的例子: D = {...} for k in D.keys().sort(): print D[k] 差一點兒就成功了——keys方法會創建一個keys的列表,然後用sort方法來將這個列表排序——但是因為sort方法會返回None,這個循環會失敗,因為它實際上是要遍歷None(這可不是一個序列)。要改正這段代碼,將方法的調用分離出來,放在不同的語句中,如下: Ks = D.keys() Ks.sort() for k in Ks: print D[k] 只有在數字類型中才存在類型轉換在Python中,一個諸如123+3.145的表達式是可以工作的——它會自動將整數型轉換為浮點型,然後用浮點運算。但是下面的代碼就會出錯了: S = "42" I = 1 X = S + I # 類型錯誤 這同樣也是有意而為的,因為這是不明確的:究竟是將字元串轉換為數字(進行相加)呢,還是將數字轉換為字元串(進行聯接)呢看在Python中,我們認為逗明確比含糊好地(即,EIBTI(Explicit is better than implicit)),因此你得手動轉換類型: X = int(S) + I # 做加法: 43 X = S + str(I) # 字元串聯接: "421" 循環的數據結構會導致循環盡管這在實際情況中很少見,但是如果一個對象的集合包含了到它自己的引用,這被稱為循環對象(cyclic object)。如果在一個對象中發現一個循環,Python會輸出一個[…],以避免在無限循環中卡住: >>> L = ['grail'] # 在 L中又引用L自身會 >>> L.append(L) # 在對象中創造一個循環 >>> L ['grail', [...]] 除了知道這三個點在對象中表示循環以外,這個例子也是很值得借鑒的。因為你可能無意間在你的代碼中出現這樣的循環的結構而導致你的代碼出錯。如果有必要的話,維護一個列表或者字典來表示已經訪問過的對象,然後通過檢查它來確認你是否碰到了循環。賦值語句不會創建對象的副本,僅僅創建引用這是Python的一個核心理念,有時候當行為不對時會帶來錯誤。在下面的例子中,一個列表對象被賦給了名為L的變數,然後L又在列表M中被引用。內部改變L的話,同時也會改變M所引用的對象,因為它們倆都指向同一個對象。 >>> L = [1, 2, 3] # 共用的列表對象 >>> M = ['X', L, 'Y'] # 嵌入一個到L的引用 >>> M ['X', [1, 2, 3], 'Y'] >>> L[1] = 0 # 也改變了M >>> M ['X', [1, 0, 3], 'Y'] 通常情況下只有在稍大一點的程序里這就顯得很重要了,而且這些共用的引用通常確實是你需要的。如果不是的話,你可以明確的給他們創建一個副本來避免共用的引用;對於列表來說,你可以通過使用一個空列表的切片來創建一個頂層的副本: >>> L = [1, 2, 3] >>> M = ['X', L[:], 'Y'] # 嵌入一個L的副本 >>> L[1] = 0 # 僅僅改變了L,但是不影響M >>> L [1, 0, 3] >>> M ['X', [1, 2, 3], 'Y'] 切片的范圍起始從默認的0到被切片的序列的最大長度。如果兩者都省略掉了,那麼切片會抽取該序列中的所有元素,並創造一個頂層的副本(一個新的,不被公用的對象)。對於字典來說,使用字典的dict.()方法。靜態識別本地域的變數名 Python默認將一個函數中賦值的變數名視作是本地域的,它們存在於該函數的作用域中並且僅僅在函數運行的時候才存在。從技術上講,Python是在編譯def代碼時,去靜態的識別本地變數,而不是在運行時碰到賦值的時候才識別到的。如果不理解這點的話,會引起人們的誤解。比如,看看下面的例子,當你在一個引用之後給一個變數賦值會怎麼樣: >>> X = 99 >>> def func(): ... print X # 這個時候還不存在 ... X = 88 # 在整個def中將X視作本地變數 ... >>> func( ) # 出錯了! 你會得到一個逗未定義變數名地的錯誤,但是其原因是很微妙的。當編譯這則代碼時,Python碰到給X賦值的語句時認為在這個函數中的任何地方X會被視作一個本地變數名。但是之後當真正運行這個函數時,執行print語句的時候,賦值語句還沒有發生,這樣Python便會報告一個逗未定義變數名地的錯誤。事實上,之前的這個例子想要做的事情是很模糊的:你是想要先輸出那個全局的X,然後創建一個本地的X呢,還是說這是個程序的錯誤看如果你真的是想要輸出這個全局的X,你需要將它在一個全局語句中聲明它,或者通過包絡模塊的名字來引用它。默認參數和可變對象在執行def語句時,默認參數的值只被解析並保存一次,而不是每次在調用函數的時候。這通常是你想要的那樣,但是因為默認值需要在每次調用時都保持同樣對象,你在試圖改變可變的默認值(mutable defaults)的時候可要小心了。例如,下面的函數中使用一個空的列表作為默認值,然後在之後每一次函數調用的時候改變它的值: >>> def saver(x=[]): # 保存一個列表對象 ... x.append(1) # 並每次調用的時候 ... print x # 改變它的值 ... >>> saver([2]) # 未使用默認值 [2, 1] >>> saver() # 使用默認值 [1] >>> saver() # 每次調用都會增加! [1, 1] >>> saver() [1, 1, 1] 有的人將這個視作Python的一個特點——因為可變的默認參數在每次函數調用時保持了它們的狀態,它們能提供像C語言中靜態本地函數變數的類似的一些功能。但是,當你第一次碰到它時會覺得這很奇怪,並且在Python中有更加簡單的辦法來在不同的調用之間保存狀態(比如說類)。要擺脫這樣的行為,在函數開始的地方用切片或者方法來創建默認參數的副本,或者將默認值的表達式移到函數裡面;只要每次函數調用時這些值在函數里,就會每次都得到一個新的對象: >>> def saver(x=None): ... if x is None: x = [] # 沒有傳入參數看 ... x.append(1) # 改變新的列表 ... print x ... >>> saver([2]) # 沒有使用默認值 [2, 1] >>> saver() # 這次不會變了 [1] >>> saver() [1] 其他常見的編程陷阱下面列舉了其他的一些在這里沒法詳述的陷阱:在頂層文件中語句的順序是有講究的:因為運行或者載入一個文件會從上到下運行它的語句,所以請確保將你未嵌套的函數調用或者類的調用放在函數或者類的定義之後。 reload不影響用from載入的名字:reload最好和import語句一起使用。如果你使用from語句,記得在reload之後重新運行一遍from,否則你仍然使用之前老的名字。在多重繼承中混合的順序是有講究的:這是因為對superclass的搜索是從左到右的,在類定義的頭部,在多重superclass中如果出現重復的名字,則以最左邊的類名為准。在try語句中空的except子句可能會比你預想的捕捉到更多的錯誤。在try語句中空的except子句表示捕捉所有的錯誤,即便是真正的程序錯誤,和sys.exit()調用,也會被捕捉到。

7. 如何進行創建Python 多重繼承求解

然而,當項目達到某種程度的復雜性之後,過程代碼通常會暴露出其根本缺陷。下面讓我們直接進入上一個示例的面向對象版本,並看看這樣有何變化。 #!/usr/bin/env python from subprocess import Popen, PIPE import re class DiskMonitor(): """Disk Monitoring Class""" def __init__(self, pattern="2[0-9]%", message="CAPACITY WARNING", cmd = "df -h"): self.pattern = pattern self.message = message self.cmd = cmd def disk_space(self): """Disk space capacity flag method""" ps = Popen(self.cmd, shell=True,stdout=PIPE,stderr=PIPE) output_lines = ps.stdout.readlines() for line in output_lines: lineline = line.strip() if re.search(self.pattern,line): print "%s %s" % (self.message,line) class MyDiskMonitor(DiskMonitor): """Customized Disk Monitoring Class""" def disk_space(self): ps = Popen(self.cmd, shell=True,stdout=PIPE,stderr=PIPE) print "RAW DISK REPORT:" print ps.stdout.read() if __name__ == "__main__": d = MyDiskMonitor() d.disk_space() 查看該代碼的面向對象版本,可以看到代碼變得更加抽象。有時,太多的抽象會導致設計問題,但是在此例中,它允許您將問題分離為更多可重用的部分。DiskMonitor 類具有 __init__ method,您可以在其中定義新的參數,並且 disk_space 函數現在是該類中的一個方法。 使用這種新的樣式,您無需更改原始代碼即可容易地重用和自定義各個部分,而使用過程代碼時則通常必須更改原始代碼。Python 多重繼承面向對象的設計的一個更加功能強大、通常也被過度使用的方面是繼承。繼承允許您在新的類中重用和自定義現有的代碼。讓我們在下一個示例中看看繼承可能像什麼樣子。 此輸出與前面帶標記的版本區別非常大,因為它只是使用頂部注入的 print 語句來列印的未經篩選的 df –h 命令結果。通過重寫 MyDiskMonitor 類中的方法,您能夠完全改變 disk_space 方法的意圖。 有關Python 解釋器說明介紹如何創建Python多線程環境淺析Python多線程問題如何進行建立Python主線程?執行Python 解釋器相關說明允許您重用其他類中的屬性的 Python 多重繼承是這個「MyDiskMonitor(DiskMonitor)」語句。您只需在定義新類的名稱時,將先前的類的名稱放在括弧內。一旦完成此步驟,您立即可以訪問其他類屬性來做自己希望的事情。但是樂趣不僅於此。通過添加另一個通過電子郵件來發送標記消息的方法。也許是將其命名為 disk_alert(self),這樣就可以進一步自定義新類。這是面向對象的設計的美妙之處;它允許有經驗的開發人員不斷重用已編寫的代碼,從而節省大量的時間。 遺憾的是,面向對象的編程也有其不利的一面。所有這些抽象都是以復雜性為代價的,如果抽象過度,可能會徹底地弄巧成拙。由於Python 多重繼承,抽象可以達到相當有害的復雜程度。您是否能夠想像只是為了編寫一個方法也要查看多個文件的情況?無論相信與否,這種情況的確會發生,並且代表了面向對象編程的不幸現實。

熱點內容
怎麼用ftp上傳網站 發布:2025-03-11 10:25:30 瀏覽:190
酷狗傳歌到手機文件夾 發布:2025-03-11 10:14:58 瀏覽:577
遺傳進化演算法 發布:2025-03-11 10:13:23 瀏覽:618
php時間戳js 發布:2025-03-11 10:11:29 瀏覽:999
連班演算法 發布:2025-03-11 10:09:50 瀏覽:56
eclipseforlinux64 發布:2025-03-11 10:09:47 瀏覽:747
宣威雲伺服器存儲 發布:2025-03-11 10:06:22 瀏覽:557
手游編程培訓 發布:2025-03-11 09:43:38 瀏覽:511
php獲取瀏覽器 發布:2025-03-11 09:03:31 瀏覽:877
安卓常駐後台需要什麼許可權 發布:2025-03-11 08:58:26 瀏覽:181