Python 物件導向課程筆記
前言
Python 物件導向
正文
基本概念
- 什麼是物件:
- 萬物皆物件
- 物件是具體物體:
- OOP(Object Oriented Programming)物件導向程式設計:
- 物件導向 or 程式導向:都是解決問題的思路
- 程式導向:關注解決問題每一個過程
- 物件導向:關注解決問題所需要的物件
- 物件 抽象出 類; 類 例項化 物件。
- 經典類 和 新式類:是(新)否(舊)繼承了 object
- 物件導向的三大特性:
屬性
- 屬性和變數的區別
- 變數是可以改變的量值(存在不同訪問許可權)
- 屬性表示物件的特性(只能通過物件訪問,物件通過變數引用,因此和變數一樣存在不同的訪問許可權)
- 類屬性和物件屬性
- 物件屬性:僅屬於物件
- 檢視物件所有屬性
obj.__dict__
,返回字典。
- 新增物件屬性
obj.age = 18
- 通過物件可以訪問到類屬性:查詢邏輯是優先查詢物件自身,如果沒找到則根據class找到物件對應的類,從類中尋找。
- 通過物件只能訪問類屬性,而不能修改。
- 只能刪除物件本身屬性(直系屬性)
- 類屬性:屬於該類的所有物件
- 類也是物件
- 增改查刪
- 查詢:和物件查詢一樣
.__dict__
- 刪除:
del class_name.xxx
- 類的屬性無法修改(只讀),物件的屬性可以直接修改。
- 類屬性被各物件所共享
__slots__ = ['xxx']
:表示該類建立的物件只能新增指定('xxx')屬性
方法
- 方法劃分:
- 例項方法:類例項化出來的例項物件,預設第一個引數必須收到一個例項
- 類方法:預設第一個引數必須收到一個類
- 靜態方法:第一個引數不預設接收
- 注意
- 一個目標的行為動作
@classmethod
裝飾器,類方法
@staticmethod
靜態方法
- 方法的使用:根據規則和呼叫,來針對不同的問題設計不同的方法
- 裝飾器的作用:在保證原本函式不改變的前提下,直接給函式增加功能
- 元類:類是由另外一個類所建立出來的,因此存在建立類物件的類。(type)
- 因此可以用 type 來手動建立型別
- 元類根據
__metaclass__
來指明
- 可以通過
.__base__
檢視父類
class Person:
__metaclass__ = xxx
- 類的建立流程:
- 檢測類物件是否有明確的mateclass屬性。
- 檢測父類中是否存在mateclass屬性。
- 檢測模組中是否存在mateclass屬性。
- 通過內建的 type 這個元類來建立這個類物件。
- 類的描述:方便合作開發(標準註釋)
- 生成專案文件
- 方法 1:內建模組 pydoc
- 方法 2:第三方模組(Sphinx;epydoc;doxygen)
- 私有化屬性(偽私有,python 沒有私有化):
- x:共有
- _x:受保護,類內部,子類內部,模組其他位置或者跨模組訪問會被 warm,跨模組時如果
from xxx import *
會失敗,本模組__all__ = ["xxx"]
表示其他模組中可以匯入。
- **x:受保護,只有類內部能用。但對於在類外的
**
和\_
效果一樣
- 因為偽私有,還是可以強行訪問,比如
xxx.__dict__
- 私有化方法:和私有化屬性類似
__init__
建立例項物件後自動呼叫該方法
- 只讀屬性:
- 方式 1:
- 方式 2:可以以
@property
使用屬性的方式來使用該方法
- 獲得使用@property,修改使用@xxx.setter,刪除使用@xxx.deleter
- 經典類 和 新式類的區別:
setattr
,通過例項.屬性 = v 時,會呼叫該方法、通過該方法 來判斷是否將屬性新增到dict字典
- 內建特殊屬性:
- 類屬性:
__dict__
:類屬性
__bases__
:類所有父類的元組
__doc__
:類的文件字串
__name__
:類名
__module__
:類定義所在的模組
- 例項屬性:
__dict__
:例項的屬性
__class__
:例項對應的類
- 引數:*args,**kwargs
- 內建特殊方法:
- 生命週期方法:
- others:
- 資訊格式化:
__str__
:print 當前類時,會直接呼叫`str也可以通過 str(例項)獲得.(面向使用者)
__repr__
:str 的次選項,也可以通過 repr()直接呼叫或者直接輸出例項(互動環境)(面向開發)
- 呼叫操作:
__call__
:讓例項具備被呼叫的能力
- 索引操作:通過實現三個內建方法
__setitem__
__getitem__
__delitem__
- 切片操作:python3 中統一由索引操作實現了
- 比較大小:
- 相等:
__eq__
== or != ,也可以再寫__ne__
針對不等單獨定義
- 大於 gt
- 大於等於 ge
- 小於 lt
- 小於等於 le
- 對於相反操作,如果只定義了其中一個,直譯器會自動反向操作
@functools.total_ordering
會自動補全組合操作
- 布林值:
__bool__
- 遍歷操作:
- 實現 for in 遍歷:
__getitem__
,記得設定停止條件 raise StopIteration("xxx")
__iter__
,優先順序更高
__next__
,變成迭代器,注意設定終止條件
- 迭代器必須有 iter 和 next 方法,可迭代物件只需要實現 iter.可迭代物件一定可以通過 for in 訪問,但可以通過 for in 迭代不一定是可迭代物件.
- 多次重複使用需要回退
- 描述器:可以描述屬性操作的物件
__set__(self,instance,owner)
__get__(self,instance,value)
__delete__(self,instance)
- 定義方式:
- property
- 先定義一個類,設定 get,set,delete.然後直接呼叫這個類(即描述器).呼叫是通過例項不是類呼叫.
- 只實現了 get,就是非資料描述器,實現 get 和 set 是資料描述器.
- 優先順序:資料描述器 > 例項屬性 > 非資料描述器
- 使用類,實現裝飾器:
__init__
接收並儲存 func,__call__
使用 func
記憶體管理機制
- python 的生命週期:
- 監聽物件生命週期:會自動呼叫
__new__
初始化建立
__del__
釋放
__init__
- id 函式獲得物件記憶體地址,hex 函式獲得對應的 16 進位制地址
- 記憶體管理機制:引用計數器+垃圾回收機制
- 儲存
- 引用計數器:對當前引用個數進行計數,系統會去檢查那些引用計數為 0 的物件,然後清除其在記憶體的空間。
- 垃圾回收:找到迴圈引用,當記憶體中有不再使用的部分時,垃圾收集器就會把他們清理掉。
- 檢視引用計數,需要包 import sys ,sys.getrefcount(物件),注意:這裡也引用了物件,所以計數器會增加 1。
- 鏈式程式設計
三大特性
- 封裝:
- 好處: 1. 使用方便 2. 使用安全 3. 便於維護
- 繼承
- 繼承的使用權,並非複製
- 優點:方便資源重用
- 單繼承 和 多繼承
- type 和 object 的區別?
python 物件導向中有兩種體系,分別是父子關係和例項關係.
- type 創造(例項化)了 object(例項)
- type 也繼承自 object(父子)
- 繼承下的影響:
- 資源的繼承:只繼承公有屬性和方法&內建方法&受保護的屬性和方法
- 資源的使用:
- 不同繼承形態的原則:
- 單繼承鏈
- 無重疊的多繼承鏈:優先左側,深度優先
- 有重疊的多繼承鏈:優先左側,廣度優先
- 新式類:C3 演算法
- cls.mro()可以檢視查詢順序
- 資源的覆蓋
- self 和 cls,誰呼叫的資源,self 和 cls 就指向誰
- 資源的累加:
- 子類比父類多一些自己特有的資源
- 在被覆蓋的資源上進行新增修改
- 經典類會產生重複呼叫的問題
- 新式類使用 super
- super(param1,param2):,沿著 mro 鏈條來呼叫 | 沿著 param2 的鏈條,找到 param1 的下一個節點.python3 版本都自動找了.
- 多型
- 概念:一個類所延伸的多種形態 and 呼叫時的多種形態.
- python 裡沒有真正意義上的多型.
- 補充
- 抽象類
- 抽象方法
- 無法直接實現, 需要使用 abc 庫
- import abc; metaclass = abc.ABCMeta; @abc.abstractmethod
- 抽象方法如果被繼承,那麼子類中一定要實現
- OOP 設計原則:
- SOLID:
- S(Single Responsibility Principle):單一職責原則 - 一個類只負責一項職責
- O(Open Closed Principle):開放封閉原則 - 對擴充套件開放,對修改關閉
- L(Liskov Substitution Principle):里氏替換原則 - 使用基類引用的地方必須能使用繼承類的方法
- I(Interface Segregation Principle):介面分離 - 如果類包含過多介面方法,儘可能的分割方法
- D(Dependency Inversion Principle):依賴倒置 - 高層模組不應該依賴底層模組