您好,登錄后才能下訂單哦!
這篇文章主要介紹了Python類的多繼承知識點有哪些的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Python類的多繼承知識點有哪些文章都會有所收獲,下面我們一起來看看吧。
Python2.2之前是沒有共同的祖先的,之后引入Object類,它是所有類的共同祖先類Object
Python2中為了兼容,分為古典類(舊式類)和新式類
Python3中全部都是新式類
新式類都是繼承自Object的,新式類可以使用super
#古典類在python2.x中運行
class A: pass
print(dir(A)) # ['__doc__', '__module__']
print(A.__bases__) # ()
a = A()
print(a.__class__) # __main__.A
print(type(a)) # <type 'instance'>
新式類
#新式類在python3.x中運行
class B: pass
print(dir(B)) # ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
print(B.__bases__) # (<class 'object'>,)
B = B()
print(B.__class__) # <class '__main__.B'>
print(type(B)) # <class '__main__.B'>
OCP原則:多用”繼承“,少修改
繼承的用途:增強基類,實現多態
多態
在面向對象中,父類、子類通過繼承聯系在一起,如果可以通過一套方法,就可以實現不同變現,就是多態
一個類繼承自多個類就是多繼承它將具有多個類的特征
多繼承很好的模擬了世界,因為事務很少單一繼承,但是舍棄簡單,必然引入復雜性,帶來了沖突
如同一個孩子繼承了來自父母雙方的特征,那么到底眼睛像爸爸還是媽媽尼?孩子究竟改像誰多一點尼?
多繼承的實現會導致編譯器設計的復雜度增加,所以現在很多語言舍棄了類的多繼承
C++支持多繼承;Java舍棄了多繼承
Java中,一個類可以實現多個接口,一個接口也可以繼承多個接口。Java的接口很純粹,只是方法聲明,繼承者必須實現這些方法,就具有了這些能力,就能干什么
多繼承可能會帶來二義性,例如,貓和狗都繼承自動物類,現在一個類多繼承了貓和狗類,貓和狗都有了shout方法,子類究竟繼承誰的shout尼?
解決方案:實現了多繼承的語言,要解決二義性,深度優先或者廣度優先
class ClassName(基類列表): 類體
多繼承帶來的路徑選擇問題,究竟繼承那個父類的特征尼?
究竟先廣度優先,還是深度優先
Python使用MRO(method resolution order) 解決類搜索順序問題。
經典算法,按照定義從左到右,深度優先策略【比如Python2.2之前,左圖的MRO算法,MyClass→D→B→A→C→A】
新式類算法,經典算法的升級,重復的只保留最后一個。【左圖MRO是:MyClass→D→B→C→A→object】
C3算法,在類被創建出來的時候,就計算除一個MRO有序列表。【Python3唯一支持的算法,左圖中MRO是MyClass→D→B→C→A→object】C3過于復雜,沒必要去記,我們只要記住【object.mro(),顯示繼承的方法,從左到右依次查找】
當類很多,繼承復雜的情況下,繼承路徑太多,很難說清什么樣的繼承路徑
團隊協作開發,如果引入多繼承,那代碼將不可控
不管編程語言是否支持多繼承,都應當避免多繼承
Pythond的面向對象,我們看到太靈活,太開放,所以要團隊守規矩
類有下面的繼承關系
文檔Document類是其他所有文檔類的抽象基類,Word、Pdf類是Document的子類
需求:為Document子類提供打印能力思路:
1、在Document中提供print方法
class Document:
def __init__(self,content):
self.coutent = content
def print(self):
print(self.coutent)
class Word(Document): pass
class Pdf(Document): pass
a = Word("tom com")
a.print() # tom com
基類提供的方法不因該具體實現,因為它未必適合子類的打印,子類中需要覆蓋重寫。
print算是一種能力 -- 打印功能,不是所有的Document的子類都需要的,所以,從這個角度出發有點問題
class Document:
def __init__(self,content):
self.coutent = content
def print(self):
print(self.coutent)
class Word(Document):
def print(self):
print("Word print {}".format(self.coutent))
class Pdf(Document): pass
a = Word("tom com")
a.print() # Word print tom com
思路二:需要打印的子類上增加
如果現有子類上直接增加,違反了OCP的原則,所以應該繼承后增加
class Document: # 不允許修改
def __init__(self,content):
self.coutent = content
def print(self):
print(self.coutent)
class Word(Document): pass # 不允許修改
class Pdf(Document): pass # 不允許修改
class PrinttableWord(Word):
def print(self):
print("PrinttableWord print {}".format(self.coutent))
print(PrinttableWord.mro()) # [<class '__main__.PrinttableWord'>, <class '__main__.Word'>, <class '__main__.Document'>, <class 'object'>]
a = PrinttableWord("tom com")
a.print() # PrinttableWord print tom com
看似不錯,如果還要提供其他類似能力,如何繼承?
應用于網絡,文檔應該具備序列化的能力,類上就應該實現序列化可序列化還可能分為使用pickle、josn、messagepack等
這個時候,發現,類又可能太多了,繼承的方式不是很好了
功能太多,A類需要某幾樣功能,B類需要另外幾樣功能,很繁瑣
思路三:裝飾器,用裝飾器增強一個類,把功能給類附加上去,那個類需要,就裝飾它
def printable(cls):
def _print(self):
print("_print 裝飾器 {}".format(self.coutent))
return _print
cls.print = _print
return cls
class Document:
def __init__(self,content):
self.coutent = content
def print(self):
print(self.coutent)
class Word(Document): pass
class Pdf(Document): pass
@printable
class PrinttableWord(Word): pass #先繼承,后裝飾
print(PrinttableWord.__dict__) # {'__module__': '__main__', '__doc__': None, 'print': <function printable.<locals>._print at 0x0173C228>}
a = PrinttableWord("tom")
a.print() # _print 裝飾器 tom
優點:簡單方便,在需要的地方動態增加
思路四:Mixin 【用類去繼承】
先看代碼
class PrintableMixin:
def print(self):
print("PrintableMixin {}".format(self.coutent))
class Document:
def __init__(self,content):
self.coutent = content
def print(self):
print(self.coutent)
class Word(Document): pass
class Pdf(Document): pass
class PrinttableWord(PrintableMixin,Word): pass
print(PrinttableWord.mro()) # [<class '__main__.PrinttableWord'>, <class '__main__.PrintableMixin'>, <class '__main__.Word'>, <class '__main__.Document'>, <class 'object'>]
print(PrinttableWord.__dict__) # {'__module__': '__main__', '__doc__': None}
a = PrinttableWord("tom")
a.print() # PrintableMixin tom
Mixin就是其他類混合進來,同時帶來了類的屬性和方法
這里看來Mixin類和裝飾器效果一樣,也什么特別的,但是Mixin是類,就可以繼承,增強功能
class PrintableMixin:
def print(self):
print("PrintableMixin {}".format(self.coutent))
class Document:
def __init__(self,content):
self.coutent = content
def print(self):
print(self.coutent)
class Word(Document): pass
class Pdf(Document): pass
class PrinttableWord(PrintableMixin,Word): pass
class SuperPrintableMixin(PrintableMixin,Word):
def print(self):
print("~"*30)
super(SuperPrintableMixin, self).print()
print("~"*30)
print(SuperPrintableMixin.mro()) # [<class '__main__.SuperPrintableMixin'>, <class '__main__.PrintableMixin'>, <class '__main__.Word'>, <class '__main__.Document'>, <class 'object'>]
print(SuperPrintableMixin.__dict__) # {'__module__': '__main__', 'print': <function SuperPrintableMixin.print at 0x018264B0>, '__doc__': None}
a = SuperPrintableMixin("tom")
a.print() # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# PrintableMixin tom
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Minxin本質上就是多繼承實現的
Mixin體現的是一種組合的設計模式
在面向對象的設計中,一個負載的類,往往需要很多功能,而這些功能有來自不同的類提供,這就需要很多的類組合在一起
從設計模式的角度來說,多組合,少繼承。
Mixin類的使用原則
Mixin類中不應該顯示的出現__init__初始化方法
Mixin類通常不能獨立工作,因為它是準備混入別的類中的部分功能實現
Mixin類的祖先類也應該是Mixin類
使用時,Mixin類通常在繼承列表第一個位置,例如:class PrintableWord(PrintableMixin,Word):pass
關于“Python類的多繼承知識點有哪些”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Python類的多繼承知識點有哪些”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。