導航:首頁 > 編程語言 > python中同名方法繼承

python中同名方法繼承

發布時間:2024-05-23 05:52:40

『壹』 python中類繼承問題

Python新式類採用MRO演算法處理繼承關系,當調用c.say()方法時首先查找C類中是否定義了say()方法,若沒有繼續查找B類中是否定義了say()方法,找到B類中定義有say()方法,因此使用B類的say()方法。

『貳』 Python中繼承的理解與運用

9.5. 繼承
當然,如果一種語言不支持繼承就,「類」就沒有什麼意義。派生類的定義如下所示:
class DerivedClassName(BaseClassName):

命名 BaseClassName (示例中的基類名)必須與派生類定義在一個作用域內。除了類,還可以用表達式,基類定義在另一個模塊中時這一點非常有用:
class DerivedClassName(modname.BaseClassName):
派生類定義的執行過程和基類是一樣的。構造派生類對象時,就記住了基類。這在解析屬性引用的時候尤其有用:如果在類中找不到請求調用的屬性,就搜索基類。如果基類是由別的類派生而來,這個規則會遞歸的應用上去。
派生類的實例化沒有什麼特殊之處: DerivedClassName() (示列中的派生類)創建一個新的類實例。方法引用按如下規則解析:搜索對應的類屬性,必要時沿基類鏈逐級搜索,如果找到了函數對象這個方法引用就是合法的。
派生類可能會覆蓋其基類的方法。因為方法調用同一個對象中的其它方法時沒有特權,基類的方法調用同一個基類的方法時,可能實際上最終調用了派生類中的覆蓋方法。(對於 C++ 程序員來說,Python 中的所有方法本質上都是 虛 方法。)
派生類中的覆蓋方法可能是想要擴充而不是簡單的替代基類中的重名方法。有一個簡單的方法可以直接調用基類方法,只要調用: BaseClassName.methodname(self, arguments)。有時這對於客戶也很有用。(要注意只有 BaseClassName 在同一全局作用域定義或導入時才能這樣用。)
Python 有兩個用於繼承的函數:
函數 isinstance() 用於檢查實例類型: isinstance(obj, int) 只有在 obj.__class__ 是 int 或其它從 int 繼承的類型
函數 issubclass() 用於檢查類繼承: issubclass(bool, int) 為 True,因為 bool 是 int 的子類。
然而, issubclass(float, int) 為 False,因為 float 不是 int 的子類。

『叄』 Python中的面向對象(高級)之私有方法、多繼承、多態

特徵:私有屬性與私有方法不能從外部被調用,也不能被子類繼承

唯一寫法:在屬性或方法前面加上__(兩個下劃線)

我們寫一個簡單的例子,創建一個類,包含私有方法、私有屬性、普通方法、普通屬性,並生成一個實例

私有屬性和私有方法可以從內部被調用(總不能我寫了,但是哪都不讓用吧)

我們試試在類里再加入一個新的方法,調用私有方法和屬性

可以看到,私有屬性和私有方法是可以在類內部被調用的。

舉個私有屬性應用場景的例子


二。object類

我們試一下


三。多繼承

一個子類可以繼承多個父類,用逗號隔開

多個父類中有同名方法時,按照繼承順序進行調用


四。多態

當不同的實例,有同名的方法時,我們可以一個函數,傳入不同的實例,執行對應的方法。

我們定義一個貓和一個狗的類,兩個類中都有'叫'的方法。並各生成一個實例。

定義一個函數,用函數來調用'叫'的方法

這就叫多態。

『肆』 Python類的繼承與多態詳細介紹

類(Class): 用來描述具有相同的屬性和方法的對象的集合。

類變數:類變數在整個實例化的對象中是公用的。類變數定義在類中且在函數體之外。類變數通常不作為實例變數使用。

類有一個名為 __init__() 的特殊方法(構造方法),該方法在類實例化時會自動調用

self:self 代表的是類的實例,代表當前對象的地址,而 self.class 則指向類。

類調用 Car.weight

實例化 car01=Car(5)

實例對象調用 car01.weght

我們在構造類時,Python3默認我們繼承了object這個基類,我個人理解object就是個空的類,可以不用管為何要在括弧中寫上object,這是Python3的特性,在python2中如果你沒有寫object的話不會默認繼承了object這個基類。

同樣的我們自己希望繼承的父類只需要把objetc改為我們自己定義的類名即可。子類中可以擁有父類中所有的公有屬性和方法,但是可以通過在變數名前加下劃線使其變為私有,這樣子類就不可以訪問父類中的成員了。

以下三個公交車類的父類均為客車類,我們可以寫一個funcs方法使得每次調用funcs方法時,傳入不同的對象以執行不同的func方法,具體實現如下:

主函數

可以看到,我將小 汽車 實例化為帶有重量為5t的一個具體對象,將客車實例化為帶有重量為20t的一個具體對象,將三個公交車實例化為帶有重量為15t的一個具體對象.

如上圖所示,我每次在調用funcs方法時都傳入了一個實例化對象,funcs根據不同的對象執行相應的內部方法。

『伍』 Python類的多重繼承問題深入分析

Python類的多重繼承問題深入分析
首先得說明的是,Python的類分為經典類 和 新式類
經典類是python2.2之前的東西,但是在2.7還在兼容,但是在3之後的版本就只承認新式類了
新式類在python2.2之後的版本中都可以使用
經典類和新式類的區別在於:
經典類是默認沒有派生自某個基類的,而新式類是默認派生自object這個基類的:
代碼如下:
# old style
class A():pass
# new style
class A(obejct):pass
2.經典類在類多重繼承的時候是採用從左到右深度優先原則匹配方法的..而新式類是採用C3演算法(不同於廣度優先)進行匹配的
3.經典類是沒有__MRO__和instance.mro()調用的,而新式類是有的.
為什麼不用經典類,要更換到新式類
因為在經典類中的多重繼承會有些問題...可能導致在繼承樹中的方法查詢繞過後面的父類:
代碼如下:
class A():
def foo1(self):
print "A"
class B(A):
def foo2(self):
pass
class C(A):
def foo1(self):
print "C"
class D(B, C):
pass
d = D()
d.foo1()
按照經典類的查找順序從左到右深度優先的規則,在訪問d.foo1()的時候,D這個類是沒有的..那麼往上查找,先找到B,裡面沒有,深度優先,訪問A,找到了foo1(),所以這時候調用的是A的foo1(),從而導致C重寫的foo1()被繞過.
所以python引入了新式類的概念,每個基類都繼承自object並且,他的匹配規則也從深度優先換到了C3
C3演算法
C3演算法是怎麼做匹配的呢..在問答版塊上面討論之後,歸結如下:
C3演算法的一個核心是merge.
在merge列表中,如果第一個序列mro的第一個類是出現在其它序列,並且也是第一個,或者不出現其它序列,那麼這個類就會從這些序列中刪除,並合到訪問順序列表中
比如:(引用問題中zhuangzebo的回答@zhuangzebo)
代碼如下:
class A(O):pass
class B(O):pass
class C(O):pass
class D(A,B):pass
class E(C,D):pass

首先需要知道 O(object)的mro(method resolution order)列表是[O,]
那麼接下來是:
代碼如下:
mro(A) = [A, O]
mro(B) = [B, O]
mro(C) = [C, O]
mro(D) = [D] + merge(mro(A), mro(B), [A, B])
= [D] + merge([A, O], [B, O], [A, B])
= [D, A] + merge([O], [B, O], [B])
= [D, A, B] + merge([O], [O])
= [D, A, B, O]
mro(E) = [E] + merge(mro(C), mro(D), [C, D])
= [E] + merge([C, O], [D, A, B, O], [C, D])
= [E, C] + merge([O], [D, A, B, O], [D])
= [E, C, D] + merge([O], [A, B, O])
= [E, C, D, A, B] + merge([O], [O])
= [E, C, D, A, B, O]

然後還有一種特殊情況:
比如:
merge(DO,CO,C) 先merge的是D
merge(DO,CO,C) 先merge的是C
意思就是.當出現有 一個類出現在兩個序列的頭(比如C) 這種情況和 這個類只有在一個序列的頭(比如D) 這種情況同時出現的時候,按照順序方式匹配。
新式類生成的訪問序列被存儲在一個叫MRO的只讀列表中..
你可以使用instance.__MRO__或者instance.mro()來訪問
最後匹配的時候就按照MRO序列的順序去匹配了
C3和廣度優先的區別:
舉個例子就完全明白了:
代碼如下:
class A(object):pass
class B(A):pass
class C(B):pass
class D(A):pass
class E(D):pass
class F(C, E):pass

按照廣度優先遍歷,F的MRO序列應該是[F,C,E,B,D,A]
但是C3是[F,E,D,C,B,A]
意思是你可以當做C3是在一條鏈路上深度遍歷到和另外一條鏈路的交叉點,然後去深度遍歷另外一條鏈路,最後遍歷交叉點
新式類和經典類的super和按類名訪問問題
在經典類中,你如果要訪問父類的話,是用類名來訪問的..
代碼如下:
class A():
def __init__(self):
print "A"
class B(A):
def __init__(self):
print "B"
A.__init__(self) #python不會默認調用父類的初始化函數的

這樣子看起來沒三問題,但是如果類的繼承結構比較復雜,會導致代碼的可維護性很差..
所以新式類推出了super這個東西...
代碼如下:
class A():
def __init__(self):
print "A"
class B(A):
def __init__(self):
print "B"
super(B,self).__init__()

這時候,又有一個問題:當類是多重繼承的時候,super訪問的是哪一個類呢?
super實際上是通過__MRO__序列來確定訪問哪一個類的...實際上就是調用__MRO__中此類後面的一個類的方法.
比如序列為[F,E,D,C,B,A]那麼F中的super就是E,E的就是D
super和按照類名訪問 混合使用帶來的坑
代碼如下:
class A(object):
def __init__(self):
print "enter A"
print "leave A"
class B(object):
def __init__(self):
print "enter B"
print "leave B"
class C(A):
def __init__(self):
print "enter C"
super(C, self).__init__()
print "leave C"
class D(A):
def __init__(self):
print "enter D"
super(D, self).__init__()
print "leave D"
class E(B, C):
def __init__(self):
print "enter E"
B.__init__(self)
C.__init__(self)
print "leave E"
class F(E, D):
def __init__(self):
print "enter F"
E.__init__(self)
D.__init__(self)
print "leave F"
這時候列印出來是:
代碼如下:
enter F
enter E
enter B
leave B
enter C
enter D
enter A
leave A
leave D
leave C
leave E
enter D
enter A
leave A
leave D
leave F

可以看出來D和A的初始化函數被亂入了兩次!
按類名訪問就相當於C語言之前的GOTO語句...亂跳,然後再用super按順序訪問..就有問題了
所以建議就是要麼一直用super,要麼一直用按照類名訪問
最佳實現:
避免多重繼承
super使用一致
不要混用經典類和新式類
調用父類的時候注意檢查類層次
以上便是本人對於python類的繼承的認識了,希望對大家能有所幫助

閱讀全文

與python中同名方法繼承相關的資料

熱點內容
app鎖定了如何驗證身份 瀏覽:466
命令與征服4正版 瀏覽:680
電池模擬模型python 瀏覽:279
文件夾分開壓縮可以嗎 瀏覽:509
片在線觀看免費觀看 瀏覽:602
鐵拳電影在線觀看免費完整版國語 瀏覽:465
android面試准備 瀏覽:113
javamysqlexcel 瀏覽:664
低價雲伺服器騰訊 瀏覽:141
智能電視機怎麼加密 瀏覽:159
簡單的ssm在線學習系統源碼 瀏覽:623
放置大師源碼 瀏覽:441
馬達加斯加鞭炮解壓 瀏覽:461
釜山行1電影在線觀看 瀏覽:386
廣州視頻流加密晶元 瀏覽:651
伺服器異常有什麼預兆 瀏覽:751
安卓airpodspro怎麼調降噪模式 瀏覽:102
承憲的朋友電影 瀏覽:780
農場互助源碼手機版 瀏覽:117
萬安如何使用雲伺服器ip 瀏覽:214