1.封裝
? ? 概念:封裝主要是指將一些屬性和相關方法封裝在一個對象中,對外隱藏內部具體實現細節
? ? 作用:1)使用起來更加方便,類似于提供了一個工具箱
? ? ? ? ? ? ? ?2)保證數據的安全(設置私有屬性)
? ? ? ? ? ? ? ?3)利于代碼維護(代碼維護時,直接在類內部修改即可,外部無需修改)
2.繼承
?2.1 繼承的基本知識
- 概念:一個類"擁有"另外一個類的"資源"(指"非私有的"屬性和方法)的使用權
- 作用:資源重用? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
- 分類:單繼承(只繼承了一個父類)、多繼承(繼承了多個父類)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
- 語法:? class 子類名(父類名):? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?pass? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??父類名可以寫多個,用逗號“,”隔開,越靠前繼承的優先級越高? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
- 常用內置屬性:__bases__?? ? ? ? ? ? ? ? ? ? 查看類的所有父類構成元組? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
- object 和 type 的區別:
? ? ? ? type:元類,是用來創建類的類
? ? ? ? object:類對象,主要是判別新式類(繼承了object類)和經典類(沒繼承object類),? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? python3版本,在創建類時,默認繼承object類,即:默認創建新式類

?2.2?繼承下的影響?
? ? 2.2.1 資源的繼承
? ? ? 在python中,繼承是指對父類資源的使用權 /訪問權
? ? ? 除了私有的屬性和私有的方法, 其他的基本都能繼承(共有、受保護、內置)
? ? ? 在子類中,不能修改父類的屬性 / 方法,修改操作相當于在子類中新增一個同名屬性
? ? 2.2.2 資源的使用
- 繼承的幾種形態以及遵循的準則
- Python3.x之后新式類的方法解析順序(MRO):C3算法
形態 | 具體描述 | 資源查找原則 |
---|---|---|
單繼承鏈 | 一個子類只有一個父類 | 遵循"從下到上"的原則 自身 一> 父類 一> 父類的父類 |
無重疊的多繼承鏈 | 繼承鏈無交叉, 無公共父類 | 遵循"單調"原則 ?順著一條鏈找到底 A?一> B 一> D 一> C 一> E |
有重疊的多繼承鏈 | 繼承鏈有交叉, 有公共父類 | 遵循"從下到上"的原則 一級一級查找 A?一> B 一> C?一> D |

- ?針對于幾種標準原則的發展演變

- 查看某個類的資源查找順序的語法:
法一(inspect包) | import? inspect? ? inspect.getmro(類名) |
法二(mro屬性) | 類名.__mro__ |
法三(mro函數) | 類名.mro() |
? ? 2.2.3?資源的覆蓋
? ? ? 資源覆蓋包括屬性的覆蓋和方法重寫。在MRO的資源檢索鏈中,若優先級高的類和優先級低的類都寫了一個一樣的資源(屬性或方法),則在獲取資源時,會優先選擇優先級高的類中的資源,而摒棄優先級低的資源,就造成了“覆蓋”的假象
? ? ? ?注意:如果子類方法調用了父類的方法,那么此時參數self和cls是調用這個方法的那個類/屬性
? ? 2.2.4 資源的累加?
? ? ? ?概念:在一個類的基礎之上, 增加一些額外的資源
- 場景一:子類相比于父類, 多一些自己特有的方法/屬性
? ? ? ? 實現方式:直接在子類中定義就可
- 場景二:在被“覆蓋”的方法基礎之上,新增新的內容(即:保留舊的某個方法并擴展新內容)
? ? ? ? 實現方式一:在高優先級類的方法中, 通過"類名"調用低優先級類的方法
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 這里不能用實例調用,會導致self輸入不一致
? ? ? ? ? ? ? ? ? ? 弊端:對于有重疊的多繼承鏈,會產生重復調用;代碼不易維護
class B:def __init__(self):self.weight = 60self.height = 1.75class A(B): # A類繼承了B類def __init__(self):B.__init__(self) # 通過類名調用B中的init,保留原來內容# 這里不能通過其他方式調用,會導致self輸入不一致self.bmi = 1 # 新增額外內容a = A()
print(a.__dict__)
? ? ?
? ? ??實現方式二:在低優先級類的方法中, 通過"super"調用高優先級類的方法
? ? ? ? ? ? ? super是一個類,它只在新式類中有效,它主要起代理作用,幫助我們沿著MRO鏈條,找到下一個節點,去調用對應方法?
? ? ? ? ? ? ? ?語法:super(). 方法名? ? ? ? ? ?在 python3.x 的版本中,不需要填寫參數,會自動補全
? ? ? ? ? ? ? ?實現原理:def super(cls參數一, inst參數二):
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mro = inst.__class__.mro()
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return mro[mro.index(cls) + 1]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 相當于沿著參數二的mro順序,找到參數一對應的節點+1,即參數一的下一個節點
# 繼承關系 A 一> B,C 一> D
# 在這種情況下,如果使用方法一在B C中調用D,再在A中調用B C,就會重復調用D兩次
# 使用super調用,就不會重復出現
class D(object):def __init__(self):print("d")class B(D):def __init__(self):super().__init__()print("b")class C(D):def __init__(self):super().__init__()print("c")class A(B,C):def __init__(self):super().__init__()print("a")A()
3.多態
- 多態大致有兩種含義:
? ? ? ? ? ? ? ? ? 1)一個類, 所延伸的多種形態(animal可以延伸出dog cat...);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2)調用時的多種形態(dog和cat中都有同一屬性/方法,但調用時輸出不同)
- 多態在python中的體現:
? ? ? ? ? 鴨子類型(動態類型的一種風格),它的關注點在于對象的"行為和屬性"; 而非對象的"類型"
- ? ? 回憶:
? ? ? ? ? ? python是強類型(類型強勢,不會輕易自動修改)、動態類型(數據的類型在運行時可以? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 判定,動態修改)? ? ? ? ? ? ? 而多態一般是體現在靜態語言中,所以在python中沒有真正意義上的多態,也不需要多態?
4.補充:抽象類、抽象方法
- 概念
? ? ? ? ?抽象類 是指一個抽象出來的類,并不是某一個具化的類,它是一個不能直接創建實例的類,? ? ? ? ? ? ? ? ? ? ? ? 主要是用于被其他類繼承
? ? ? ? ?抽象方法 是指抽象出來的一個方法,不具備具體實現,不能直接調用? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?如果一個類中有抽象方法,當他被繼承時,繼承他的類中必須要具體定義這個方法
- 例子:
? ? ? ? ? ?animal類就是一個抽象類,他只是存儲了所有動物的一些特性,但并不能直接去使用,因? ? ? ? ? ? ? 為我們不知道到底是什么動物,同理animal的各種方法,如體型聲音等也是如此
- 在python中的實現:
? ? ? ? ? 導入模塊abc? ——> 設置類的元類為abc.ABCMeta? ——>? 使用裝飾器裝飾抽象方法? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@abc.abstractmethod
5.案例?
- 要求:
? ? ? ? ?1. 定義三個類, 小狗, 小貓, 人
? ? ? ? ?2.三個類具體要求如下:
? ? ? ? ? ? 小狗: 姓名, 年齡(默認1歲); ? ?吃飯, 玩, 睡覺, 看家(格式: 名字是xx, 年齡xx歲的小狗在xx)
? ? ? ? ? ? 小貓: 姓名, 年齡(默認1歲);? ?吃飯, 玩, 睡覺, 捉老鼠(格式: 名字是xx, 年齡xx歲的小貓在xx)
? ? ? ? ? ??人: ? 姓名, 年齡(默認1歲), 寵物; ?吃飯, 玩, 睡覺(格式: 名字是xx, 年齡xx歲的人在xx)
? ? ? ? ? ? ? ? ? ? 養寵物(讓所有的寵物吃飯, 玩, 睡覺),?
? ? ? ? ? ? ? ? ? ? 寵物工作(讓所有的寵物根據自己的職責開始工作)?
# 案例
# 我們發現在三個大類中,有很多相同的屬性,所以我們可以先定義一個父類,讓他們都繼承即可class Animal():def __init__(self, name, age=1):self.name = nameself.age = agedef eat(self):print(f"{self}吃飯")def play(self):print(f"{self}玩")def sleep(self):print(f"{self}睡覺")class Person(Animal): #定義人# 在創建小狗實例時,給它設置幾個屬性,所以這里應該定義實例屬性def __init__(self,name,pet,age=1):super(Person,self).__init__(name,age)self.pet = petdef __str__(self): # self本身的一個字符串描述 print(self)直接輸出下面字符串return f"名字是{self.name}, 年齡{self.age}歲的人在"def yangPets(self):for pet in self.pet:pet.eat()pet.play()pet.sleep()def petWork(self):for pet in self.pet:pet.work()class Dog(Animal): #定義狗類# 在創建小狗實例時,給它設置幾個屬性,所以這里應該定義實例屬性def __init__(self, name, age=1):super(Dog,self).__init__(name,age)def work(self):print(f"{self}看家")def __str__(self): # self本身的一個字符串描述 print(self)直接輸出下面字符串return f"名字是{self.name}, 年齡{self.age}歲的小狗在"class Cat(Animal): #定義貓類# 在創建小貓實例時,給它設置幾個屬性,所以這里應該定義實例屬性def __init__(self, name, age=1):super(Cat,self).__init__(name,age)def work(self):print(f"{self}捉老鼠")def __str__(self): # self本身的一個字符串描述 print(self)直接輸出下面字符串return f"名字是{self.name}, 年齡{self.age}歲的小貓在"d = Dog("卡布",5)
c = Cat("喵喵",3)
p = Person("李明",[d,c],25)p.yangPets()
p.petWork()
6.總結:面向對象原則 SOLID(了解)
- S:單一職責原則(一個類只負責一項職責)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
- O:開放封閉原則(對擴展開放,對修改關閉)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
- ?L:里氏替換原則(使用父類引用的地方必須能使用子類對象)??
?? ? - ?I:接口分離原則(如果類包含了過多的接口方法,而這些方法在使用的過程中并非"不可分? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 割", 那么應當把他們進行分離)
? ? ??所謂接口, 在Python中, 可以簡單的理解為"抽象方法? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? - ?D:依賴倒置原則(高層模塊不應該直接依賴低層模,他們應該依賴抽象類或者接口塊)
?? ?
?? ?
?