Inheritance Of Python 類的繼承
Inheritance OOP三要素之一,繼承
人類和貓都繼承自動物類。
個體繼承自父母,集成了父母的一部分特征。
在面向對象的世界中,從父類繼承,就可以直接擁有弗雷德屬性和方法,這樣可以減少代碼,多復用。子類可以定義自己的屬性和方法。
類的繼承
對於python來講,所有的祖先都是object,所有的類都繼承自object
class Animal:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
def shout(self
print(‘Animal shout‘)
class Cat(Animal):# 子類繼承父類
def shout(self):
print(‘miao‘) # override
class Persian(Cat): #看一下__dict就知道繼承了什麽屬性
def __init__(self):
self.eyes = ‘blue‘
class Dog(Animal):
def run(self):
print(‘Dog run‘)
tom = Cat(‘tom‘)
print(tom.name)
print(tom.__dict__
dog = Dog(‘ahuan‘)
print(dog.name)
dog.shout()
ani = Animal(‘monster‘)
ani.shout()
cat = Cat(‘garfield‘)
cat.shout()
print(cat.name)
tom
{‘_name‘: ‘tom‘}
ahuan
Animal shout
Animal shout
miao
garfield
增加了代碼的復用,減少了冗余。
有自己的特點,先繼承,再覆蓋
從上面的例子看出,通過繼承,子類不用寫代碼,直接繼承了父類的屬性和方法。
Inheritance
Superclass父類,fatherclass ,基類
childclass ,派生類
object類,python2.2之後引入的,它是所有類的共同祖先類。
Python2 中為了兼容,分為古典類和新式類。
python3之後都是是新式類
新式類都是繼承自object的,新式類可以使用super。
父類的就是你的,傳什麽就是什麽,如self。
實例繼承的屬性,放在實例類的實例上,即實例的一定放在實例上。只是self.的。類的放在類屬性上。
私有的都是不可訪問的
多繼承
OCP原則:多繼承、少修改
繼承的用途:增強基類、實現多態
多態:
在OOP中,superclass和childclass是通過繼承聯系在一起,如果通過一套方法,實現不同表現就是多態。
一個類繼承自多個類就是多繼承,它將具有多個類的特征。
多繼承的弊端
帶來路徑選擇問題,究竟繼承哪個superclass的feature
MRO(method resolution order)
Python 使用MRO解決基類搜索順序問題。
解決base class 搜索順序
MRO三種resolution order
classic,從左到右,深度優先策略。2.2之前是MyClass,D,B,A,C,A
新式類,重復的只保留最後一個。MyClass,D,B,C,A,object
C3算法,在類被創建出來的時候,就計算出一個MRO有序列表。.MRO,返回一個有序列表。解決了多繼承的二義性。
lst = MyClass,D,B,C,A,object
多繼承的缺點
類很多,繼承復雜,繼承路徑太多,很難說清什麽樣的繼承路徑,語法允許多繼承,但解釋執行時執行時候才發現錯誤。
團隊協作開發,如果引入多繼承,代碼不可控。
不論是否支持多繼承,都應當避免多繼承。
Python的面向對象,太靈活,太開放,註重規矩。
增加需求
不完整的一個類,臨時使用,用上多繼承的方法,組合
新建一個需要的子類,可以增加和覆蓋原有不便的方法,這時候實例是子類的實例。
需求:
為Document子類提供打印能力
思路:
1、在Document中提供print方法
基類提供的方法不應該具體實現,子類需要覆蓋重寫。print算是一種能力,不是所有的Document子類都需要。
2、需要打印的子類上增加
繼承後增加,不用在子類上直接增加,遵循了OCP原則。但是如果遇到需要不確定的多項功能時,需要增加的子類過多。
3、裝飾器
printable相當於把PrintableWord的名字,即這個標示符拿去,就是拿了這個類(函數)對象,作為參數放到printable函數裏。給它添加了一個print方法(類對象是可以動態增加類屬性的)(數據的叫屬性,非數據的叫方法),類對象的__dict,類本身沒有變化。
運行時類對象與print函數綁定,將類對象作為第一參數傳入。
class Printable:
def _print(self):
print(self.content)
class Document:
def __init__(self, content):
self.content = content
class Word(Document): pass
class Pdf(Document): pass
def printable(cls):
cls.print = lambda self: print(self.content)
return cls
@printable # PrintableWord=printable(PrintableWrod)
class PrintableWord(Wrod): pass
在需要的地方動態增加,直接使用裝飾器,不需要對類進行修改。
Mixin
原則:Mixin應當覆蓋或替換類的功能,在繼承列表的最左邊。
class PrintableMxixin:
def print(self):
print(‘--------------------------‘)
print(‘{}‘.format(self.content))
print(‘--------------------------‘)
class Document:
def __init__(self, content):
self.content = content
def print(self):
print(self.content)
class Word(Document): pass
class PrintableWord(Word):pass
class Pdf(Document): pass
class PrintablePdf(PrintableMxixin, Pdf): 如果將Mixin放在右邊則改變了mro,使用Document的print方法。
pass
print(PrintablePdf.mro())
pdf = PrintablePdf(‘teset\nabc‘)
print(pdf.__dict__)
pdf.print()
[<class ‘__main__.PrintablePdf‘>, <class ‘__main__.PrintableMxixin‘>, <class ‘__main__.Pdf‘>, <class ‘__main__.Document‘>, <class ‘object‘>]
{‘content‘: ‘teset\nabc‘}
--------------------------
teset
abc
--------------------------
Mixin就是其他類混合進來,同時帶來了類的屬性和方法。
Mixin是類,可以繼承。
Mixin類的使用原則
Mixin類中不應該顯示的出現__init__初始化方法
Mixin類通常不能獨立工作,因為它是準備混入別的類中的部分功能實現
Mixin類的祖先類也應該是Mixin類
Inheritance Of Python 類的繼承