1. 程式人生 > >08-Python面向物件-面向物件實踐

08-Python面向物件-面向物件實踐

學習地址:

撩課-Python大資料+人工智慧1
撩課-Python大資料+人工智慧2
撩課-Python大資料+人工智慧3
撩課-Python大資料+人工智慧4
撩課-Python大資料+人工智慧5
撩課-Python大資料+人工智慧6
撩課-Python-GUI程式設計-PyQt5

1.如何定義一個類?

		class 類名:
        pass

2.怎樣通過類,創建出一個物件?

		根據類建立物件
			one = Money()
		執行流程
			1. 類的定義
			2. 根據類,創建出一個物件
			3. 將物件的唯一標識返回

3.屬性相關

1).屬性和變數的區別及判定依據?
			區別
				概念
					變數是“可以改變的量值”
					屬性是“屬於某個物件的特性”
				訪問許可權
					變數:根據不同的位置,存在不同的訪問許可權
						全域性變數
						區域性變數
						...
					屬性:只能通過物件來進行訪問
						所以,必須先找到物件
						物件也是通過變數名來引用;而既然是變數,也有對應的訪問許可權
			判定依據
				是否存在宿主

2).物件屬性

1).怎樣讓一個物件擁有一些屬性?(增)

				1. 直接通過物件,動態新增
					語法:
					物件.屬性 = 值
				2. 通過類的初始化方法(構造方法)
					__init__方法

怎樣訪問一個物件的屬性?(查)

				一般訪問
					物件.屬性
				如果訪問不到
					會直接報錯
					需要記住錯誤提示
			怎樣修改一個物件的屬性?(改)
				同新增一樣;系統會自動識別,不存在則新增,存在則修改
				語法
					物件.屬性 = 值
			怎樣刪除一個物件的屬性?(刪)
				del 物件.屬性
			補充:
				檢視物件的所有屬性?
				物件.__dict__
2).類屬性
			萬物皆物件,類也是一個物件
				比如,生產月餅的模板,對於月餅來說它是“類”
				但模板本身是不是也是一個具體的東西,也是由其他的東西創建出來的??
			怎樣讓一個類擁有屬性?(增)
				方式1
					類名.類屬性 = 值
				方式2
					class Dog:
	dogCount = 0

怎樣查詢一個類的屬性?(查)

				通過類訪問
					類名.類屬性
				通過物件訪問
					物件.類屬性
				注意:
					為什麼可以通過物件訪問到類屬性?
					答:和Python物件的屬性查詢機制有關
						優先到物件自身去查詢屬性
							找到則結束
						如果沒有找到
							則根據__class__找到物件對應的類
							到這個類裡面查詢

怎樣修改一個類的屬性?(改)

				通過類名改
					語法如同給類增加一個屬性的方式1
						系統也會自動檢測
						不存在,則新增
						存在,則修改
					類名.屬性 = 值
				能否通過物件改?
					不能!

怎樣刪除一個類的屬性?(刪)

				通過類名刪除
					del 類名.屬性
				能否通過物件刪除?
					不能!
					del 語句只刪除直系屬性
			注意
				類屬性的記憶體儲存問題
					一般情況下,屬性儲存在__dict__的字典當中
						有些內建物件沒有這個__dict__屬性
					一般物件可以直接修改__dict__屬性
					但類物件的__dict__為只讀;預設無法修改
						可以通過setattr方法修改
				類屬性被各個物件共享
					類屬性修改之後,所有的物件訪問到的類屬性都會跟著修改
			補充
				檢視一個類的所有屬性
				類名.__dict__

物件屬性和類屬性之間的區別聯絡?

			儲存不同
			抽象層級不同
			宿主不同
			案例考察
				類
					class Person:
    count = 1
				物件
					p = Person()
				問
					p.count += 1
						程式碼執行之後
					Person.count 與 p.count 列印的結果分別是多少?
		高階

如何限制物件的屬性?

				通過設定類屬性:__slots__
				這個屬性是一個列表
					列表中的元素,即為通過這個類創建出的物件可以新增的物件屬性
					如果這個類例項出的物件,添加了非列表之內的屬性,則會報錯

4.方法相關

方法的概念

			描述一個目標的行為動作
				比如描述一個人怎樣吃,怎樣喝,怎樣玩...
			和函式非常類似
				都封裝了一系列行為動作
				都可以被呼叫的之後,執行一系列行為動作
				最主要的區別就是:呼叫方式

方法的劃分

			例項方法
				預設第一個引數需要接收到一個例項
			類方法
				預設第一個引數需要接收到一個類
			靜態方法
				靜靜的看著前面倆裝逼,第一個引數啥也不預設接收
			注意
				1. 劃分的依據是:方法的第一個引數必須要接收的資料型別
				2. 不管是哪一種型別的方法,都是儲存在類當中;沒有在例項當中的
				3. 不同型別方法的呼叫方式不同
					但,不管怎麼調,把握一個原則
					不管是自己傳遞,還是直譯器幫我們處理;最終要保證不同型別的方法第一個引數接收到的資料,是他們想要的型別
		例項方法
			class Person:
	def run(self):
		pass
			類呼叫
				注意
					必須傳遞一個物件,因為例項方法要求呀
			物件呼叫
				不用手動傳,直譯器會預設把呼叫物件本身傳遞過去
			注意
				一般使用物件來呼叫
		類方法
			class Person:
	@classmethod
	def countPerson(cls):
		pass
			類呼叫
				不用手動傳遞第一個引數,會自動的把呼叫的類本身給傳遞過去
			物件呼叫
				不用手動傳遞第一個引數,會自動的把呼叫的物件對應的類給傳遞過去
			注意
				一般使用類來呼叫
		靜態方法
			class Person:
	@staticemethod
	def countPerson():
		pass
			類呼叫
				直接呼叫就可以, 不需要考慮第一個引數
			物件呼叫
				直接呼叫就可以
			注意
				具體使用誰來呼叫,根據場景,哪個比較適合方便就使用哪個

補充

			函式和方法的區別?
				是否有宿主
				函式都是獨立的個體,函式之間幾乎沒有共享的資料
				方法有宿主
			self-注意點
				代表呼叫的物件
				子主題 2

類相關補充

			元類
				概念
					建立類物件的類
						物件怎樣產生的?
							由類創建出來的
						類是不是物件?
							是
						所以,類物件是不是由另外一個類創建出來的?
							是
							元類
					結構圖

類物件的建立方式以及建立流程

					建立方式
						通過class 定義
							當我們這麼寫這個類描述的時候, 直譯器會自動的幫我們建立對應的類物件
						通過type函式進行建立
					類的建立流程
						1. 檢測類中是否有明確 __metaclass__屬性
							有, 則通過指定元類來建立這個類物件
						2. 檢測父類中是否存在__metaclass__屬性
							有, 則通過指定元類來建立這個類物件
						3. 檢測模組中是否存在__metaclass__屬性
							有, 則通過指定元類來建立這個類物件
						4. 通過內建的type這個元類,來建立這個類物件
				元類的應用場景
					1)   攔截類的建立
					2)   修改類
					3)   返回修改之後的類
					後面補充
			類的描述
				目的
					方便理清邏輯思路
					方便多人合作開發時的溝通
					方便生成專案文件
					...
				描述方式
					直接在類的下方,使用三個 "雙引號"對就可以
					需要註明類的作用, 以及類屬性描述
					至於方法, 則直接在方法下,使用三個"雙引號"對描述即可
						作用
						引數
						返回值
				生成專案文件(補充)
					方式1
						使用內建模組
							pydoc
						具體步驟
							檢視文件描述
								python3 -m pydoc 模組名稱
							啟動本地服務, 瀏覽文件
								python3 -m pydoc -p 1234
							生成指定模組html文件
								python3 -m pydoc -w 模組名稱
					方式2
						使用三方模組
							Sphinx
							epydoc
							doxygen
						具體步驟
							目前感興趣了可以先自行研究
							後續講完"包和模組"之後,會進行補充

屬性相關補充

			私有化屬性
				概念
					是指將一些原本公開的屬性設定許可權, 只能小範圍訪問, 其他地方訪問不了
				意義
					保證資料的安全性
					提高程式碼的可維護性
				注意
					Python並沒有真正的私有化支援,但是, 可以使用下劃線完成偽私有的效果
					類屬性(方法)和例項屬性(方法)遵循相同的規則
				x
					公有屬性
						類內部訪問
						子類內部訪問
						模組內其他位置訪問
							類訪問
								父類
								派生類
							例項訪問
								父類例項
								派生類例項
						跨模組訪問
							import形式匯入
							from 模組 import * 形式匯入
				_y
					受保護屬性
						類內部訪問
						子類內部訪問
						模組內其他位置訪問
							類訪問
								父類
								派生類
							例項訪問
								父類例項
								派生類例項
						跨模組訪問
							import形式匯入
							from module import * 形式匯入
								有__all__指明對應變數
								沒有__all__指明對應變數
				__z
					私有屬性
						類內部訪問
						子類內部訪問
						模組內其他位置訪問
							類訪問
								父類
								派生類
							例項訪問
								父類例項
								派生類例項
						跨模組訪問
							參照單下劃線開頭變數的訪問原則
					私有屬性的實現機制
						名字重整(Name Mangling)
							重改__x為另外一個名稱, 如
								_類名__x
						目的
							防止外界直接訪問
							防止被子類同名稱屬性覆蓋
					應用場景
						資料保護
						資料過濾
				補充
					xx_
						"變數名_" 這個格式是為了與系統屬性作區分
					__xx__
						兩端__一般為系統內建屬性或方法, 所以以後命名注意避免

只讀屬性

				概念
					一個屬性(一般指例項屬性), 只能讀取, 不能寫入
				應用場景
					有些屬性, 只限在內部根據不同場景進行修改, 而對外界來說, 不能修改, 只能讀取
					比如
						電腦類的網速屬性, 網路狀態屬性
				方式1
					方案
						全部隱藏
							私有化
								既不能讀
								也不能寫
						部分公開
							公開讀的操作
					具體實現
						私有化
							通過"屬性前置雙下劃線"實現
						部分公開
							通過公開的方法
							優化
								property
									作用
										將一些"屬性的操作方法"關聯到某一個屬性中
									概念補充
										經典類
											沒有繼承(object)
										新式類
											繼承(object)
										Python2.x版本定義一個類時, 預設不繼承(object)
										Python3.x版本定義一個類時, 預設繼承(object)
										建議使用
											新式類
									property
										在經典類中
											只能管理一個屬性的讀取操作
										在新式類中
											可以管理一個屬性的刪改查操作
				方式2
					方案
						藉助系統內建的方法進行攔截
					具體實現
						__setattr__方法
							當我們使用 "例項.屬性 = 值" 這種格式給一個例項增加或修改屬性的時候,
							都會呼叫系統內建的這個方法
							在這個方法的內部, 才會真正的把屬性以及對應的值給儲存到 __dict__當中
						解決方案
							在這個方法中, 進行攔截
			內建特殊屬性
				類屬性
					__dict__ : 類的屬性
					__bases__ : 類的所有父類構成元組
					__doc__ :類的文件字串
					__name__: 類名
					__module__: 類定義所在的模組
				例項屬性
					__dict__ : 例項的屬性
					__class__: 例項對應的類
		方法相關補充
			私有化方法
				私有方法
					def __方法():
	pass
				注意
					不要定義 "_類名__方法名" 這種方法

內建特殊方法

				生命週期方法(下一小節單獨介紹)
				其他內建方法
					資訊格式化操作
						__str__方法
							作用
								一個物件的描述字串, 更加方便使用者閱讀, 對使用者更友好
							觸發方式
								print 列印一個物件時
								str() 函式時
							格式
								def __str__(self):
	return "描述資訊"
						__repr__方法
							作用
								一個物件的描述字串, 更加方便機器處理, 對機器更友好(開發人員檢視)
							觸發方式
								當我們在互動模式下, 直接執行某個變數, 就會輸出對應資訊
								repr() 函式時
							格式
								def __repr__(self):
	return "描述資訊"
							注意
								一般情況下, 應滿足如下等式
									obj == eval(repr(obj))
								或者描述一個例項詳細的資訊(類名等等)
					呼叫操作
						__call__方法
							作用
								使得“物件”具備當做函式,來呼叫的能力
							使用
								1. 實現例項方法 __call__
								2. 那麼建立好的例項, 就可以通過函式的形式來呼叫
									例項(引數)
							應用場景
								有點類似於之前所講的"偏函式"的應用場景
								可以將"常變引數"和"不常變引數"進行分離
							案例
								不同型別的筆, 畫不同的圖形

索引操作

						作用
							可以對一個例項物件進行索引操作
						步驟
							1. 實現三個內建方法
								設定元素的方法
									def __setitem__(self, key, value):
								獲取元素的方法
									def __getitem__(self, item):
								刪除元素的方法
									def __delitem__(self, key):
							2. 可以以索引的形式操作物件
								增/改
									p[1] = 666
									p["name"] = "sz"
								查
									p["name"]
									p[1]
								刪
									del p["name"]
									del p[1]

切片操作

						作用
							可以對一個例項物件進行切片操作
						步驟
							Python2.x
								1. 實現三個內建方法
									__setspice__
										設定某個元素切片時呼叫
									__getspice__
										獲取某個元素切片時呼叫
									__delspice__
										刪除某個元素切片時呼叫
								2. 可以直接按照切片的方式操作物件
									p[1, 6, 2]
								注意: 過期
							Python3.x
								統一由"索引操作"進行管理
									def __setitem__(self, key, value):
									def __getitem__(self, item):
									def __delitem__(self, key):

比較操作

						作用
							可以自定義物件 "比較大小, 相等以及真假" 規則
						步驟
							實現6個方法
								相等
									__eq__
								不相等
									__ne__
								小於
									__lt__
								小於或等於
									__le__
								大於
									__gt__
								大於或等於
									__ge__

注意

	    如果對於反向操作的比較符, 只定義了其中一個方法,但使用的是另外一比較運算,那麼, 直譯器會採用調換引數的方式進行呼叫該方法
								例如
									定義了 "小於" 操作
										x < y
									使用 x > y
										會被調換引數, 呼叫上面的 "小於操作"
							但是, 不支援疊加操作
								例如
									定義了 "小於" 和 "等於" 操作
									不能使用 x <= y
						    補充
							使用裝飾器, 自動生成"反向" "組合"的方法
								步驟
									1. 使用裝飾器裝飾類
										@functools.total_ordering
									2. 實現
										> 或 >= 或 < 或 <= 其中一個
										實現 ==
							上下文環境中的布林值
								__bool__

遍歷操作

						怎樣讓我們自己建立的物件可以使用for in 進行遍歷?
							實現__getitem__方法
								優先順序低
								每次for in 獲取資料時, 都會呼叫這個方法
							或者
							實現__iter__方法
								優先順序高
								這個方法, 必須返回一個"迭代器"; 
即, 具備"__iter__"和"__next__"方法
								當for in 遍歷這個物件時, 會呼叫這個__iter__方法返回的迭代器物件的__next__方法
						怎樣讓我們自己建立的物件可以使用next函式進行訪問?
							實現__next__方法
						補充
							1. __iter__方法可以恢復迭代器的初始化值, 複用迭代器
							2. "可迭代" 與 "迭代器"必須實現的方法
							3. iter方法的使用

描述器

						概念
							可以描述一個屬性操作的物件
								物件
								屬性的操作
									增/改
									刪
									查
								描述
						作用
							可以代為管理一個類屬性的讀寫刪操作, 在相關方法中, 對資料進行驗證處理, 過濾處理等等
							如果一個類屬性被定義為描述器,那麼以後對這個類屬性的操作(讀寫刪), 都將由這個描述器代理
						定義
							定義方式1
								property
							定義方式2
								三個方法
									__get__
									__set__
									__delete__
						呼叫細節
							使用例項進行呼叫
								最多三個方法都會被呼叫
							使用類進行呼叫
								最多會呼叫get方法
							不能夠順利轉換的場景
								新式類和經典類
									描述器僅在新式類中生效
								方法攔截
									一個例項屬性的正常訪問順序
										例項物件自身的__dict__字典
										對應類物件的__dict__字典
										如果有父類, 會再往上層的__dict__字典中檢測
										如果沒找到, 又定義了__getattr__方法, 就會呼叫這個方法
									而在上述的整個過程當中, 是如何將描述器的__get__方法給嵌入到查詢機制當中?
									就是通過這個方法進行實現
										__getattribute__
										內部實現模擬
											如果實現了描述器方法__get__就會直接呼叫
											如果沒有, 則按照上面的機制去查詢

注意

							"資料描述器"和"非資料描述器"
								如果實現了
									_get__
									判定為"非資料描述器"
								如果實現了
									__get__
									__set__
									判定為"資料描述器"
							描述器和例項屬性同名時, 操作的優先順序問題
								資料描述器 > 例項字典 > 非資料描述器

裝飾器

						使用類當做裝飾器來使用