【Python學習】python學習手冊--第二十六、二十七章 類代碼編寫基礎和實例

類產生多個實例對象

從底層來看,類幾乎就是命名空間。從OOP模型來看,編程中有兩種對象:類對象和實例對象。類對象提供默認行爲,是實例對象的工廠。實例對象是程序中實際使用的處理對象,雖然可能來自同一個類,但是都有自己各自的命名空間類對象是通過語句定義的,而實例對象是類對象調用產生的,類是產生實例的工廠

類對象提供默認行爲

用class語句會創建類對象。

  • class語句會創建一個類對象,並將該對象的引用賦值給變量名(類名),他們都是在導入其所在文件時執行。這一點與def語句類似。
  • class內的賦值語句會創建類的屬性。類也是命名空間,該空間中的屬性也可以用“點”運算調用。
  • 類屬性提供對象的狀態和行爲。

實例對象是具體的元素

  • 像函數那樣調用類對象會創建新的實例對象。
  • 每個實例對象繼承類的屬性並獲得了自己的命名空間。
  • 在類的方法內,對self的屬性做賦值運算會產生每個實例自己的屬性。在類方法內,self就代表了由該類創建的實例對象。對self屬性的賦值就是對實例對象中屬性的賦值。
>>> class firstclass:         #定義了一個類
...     def setvalue(self,value):
...         self.testvariable=value
...     def printself(self):
...         print(self.testvariable)
...
>>> test=firstclass()         #構造了一個實例對象
>>> test.printself()          #現在調用打印會報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in printself
AttributeError: 'firstclass' object has no attribute 'testvariable'
>>> test.setvalue(1234)       #用方法賦值後創建了屬性
>>> test.printself()          #正常打印
1234
>>> 

類通過繼承進行定製

在Python中,實例從類中繼承,而類繼承於超類:

  • 超類列在了class頭語句中的括號內
  • 類從超類中繼承屬性。
  • 實例會繼承所有可讀取類的屬性
  • 每個object.attribute都會開啓新的獨立搜索。python會對每個屬性表達式進行類樹的獨立搜索。
  • 邏輯修改是通過創建子類,而不是修改超類。在子類中重新定義要修改的函數或變量名,就可以由子類對象取代並定製所繼承的行爲。
>>> class secondclass(firstclass):      #繼承firstclass
...   def setvalue(self,value):         #修改了函數
...       self.testvariable2=value 
...   def printself(self):
...       print(self.testvariable2)
... 
>>> test2=secondclass()
>>> test2.setvalue(12345)
>>> test2.testvariable           #函數設置的變量變爲testvariable2,函數的作用改變了。
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'secondclass' object has no attribute 'testvariable'
>>> test2.testvariable2
12345
>>> test2.printself()
12345
>>> test.printself()         #完全不應該之前對象的使用,提供代碼的複用性
1234
>>> 

Python的類也存在於模塊文件中,因此類也是屬於模塊的屬性,模塊反應的是一個Python文件,而類只是文件中的語句。按照慣例,Python中的類名應該以一個大寫字母開頭,以便更好的與模塊名區分開來。

類可以截獲運算符

通過對類中特定方法名稱的定義,可以讓python程序響應相應的運算符(運算符重載)。運算符的運算都要經過類的實現來控制。
運算符的重載可以讓自己定義的類,像內置對象一樣可以用運算符進行特定的運算。運算符重載主要有以下幾個概念:

  • 以雙下劃線命名的方法__X__是特殊的鉤子。Python運算符重載是用特殊的方法來攔截相應的運算符,比如當類中出現了__add__方法,就會攔截+運算。Python的運算符與特殊命名方法之間,定義了固定不變的映射關係
  • 當實例出現在運算中時,這類特殊的相應的方法會自動調用。(這有點像響應函數,固定的方法相應特定的運算符。)
  • 類可覆蓋(重載)多數內置運算符。有幾十種特殊運算符重載的方法的名稱,幾乎可截獲並實現內置類型的所有運算。
  • 運算符覆蓋方法沒有默認參數,也不需要。如果類中沒有定義運算符的重載方法,那麼說明該類不支持該運算。
  • 運算符可讓類與Python的對象模型相集成。

>>> class thirdclass(secondclass):
...    def __add__(self,other):             #重載了運算符+,讓類對象中的變量做運算加法。執行self+other運算
...         return(self.testvariable2+other)
... 
>>> test3=thirdclass()
>>> test3.setvalue(111)
>>> test3+333
444
>>> 

運算符重載的方法是可選的,主要是Python程序員開發工具的人在使用,而不是Python應用程序人員使用,在很多情況下,定義一些方法比重載運算來得更方便與明確。
作爲類的設計者,可以選擇或者不選擇運算符的重載,這取決於有多想讓你的類看上去是內置類型。一般來說,只有遇到數據類型爲數學對象時,纔會有可能使用運算符重載。
特殊參數self和__init__構造函數,是python中OOP的兩個基石。
使用print函數打印對象信息時,實際上是調用的對象的__str__方法返回的字符串。

在擴展子類時,可以在定製子類的函數時,調用父類的方法(從邏輯上來說就是在父類的基礎上進行修改或增強,提高了代碼的可維護性)。

面向對象編程的幾個重要概念

  • 實例創建:創建的實例,填充實例的屬性,各個實例之間都是獨立的命名空間,哪怕是相同類產生的
  • 行爲方法:操作實例中的屬性是通過類中的行爲方法來封裝邏輯的。
  • 運算符重載:類中可以對Python中的運算符進行重載,比如打印print對應函數__str__
  • 定製行爲:重新定義子類中的方法使其特殊化,在子類中可以調用父類的方法,以達到在父類基礎上的定製邏輯,提供代碼的複用性,可維護性。
  • 定製構造函數:複用父類的構造函數,定製子類自己的構造函數。

對象持久化

Python程序在運行時,都是在內存中運行。如果推出程序,內存釋放後,對象將消失,所以就要使用持久化功能,將對象保存起來。
Python提供三個標準的庫模塊來實現:
- pickle:任意對象和字節串之間的序列化,對內存中的任意的Python對象,它都能轉化成爲字節串,並可以導入內存重新使用。
- dbm:實現以鍵訪問的文件系統,可以存儲字符串
- shelve:使用另外兩個模塊,按照鍵把python系統存儲在文件中,綜合了以上兩個模塊,通過鍵來訪問或獲取指定的字節串。shelve可以在編程的時候很像字典,但是與它唯一的區別就是,在使用之前要像文件一樣打開,並像shelve對象內添加“鍵(任意的字符串)\值(這裏的值可以是任何python對象)”,並在使用完成之後關閉。

import shelve
db = shelve.open("filename")
for object in dict:
    db(object)=dict[object]
db.close()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章