類 OOP

類和實例的主要差異在於,類是一種產生實例的工廠。

類和模塊的一個差異:內存中特定模塊只有一個實例(所以我們得重載模塊以取得其新代碼),每個模塊只有一個副本會導入某一個程序中(事實上,我們必須調用reload來更新單個模塊對象,反映出來對該模塊的修改,這就是原因之一),但是,對類而言,只要有需要,製作多少實例都可以。

Python把隱含的實例傳進方法中的第一個特殊的參數,習慣上將其稱爲self

類連接至其超類的方式是,將超類列在類頭部的括號內。其從左至右的順序會決定樹中的次序。

class C1(C2,C3):

如果你使用過C++或Java,就知道Python的self相當於this,但是Python中的self一定是明確寫出來的,這樣使屬性的讀取更爲明顯。

就像簡單變量一樣,類和實例屬性並沒有事先聲明,而是在首次賦值時它的值纔會存在。

從基本的角度來說,類其實就是由函數和其他變量名所構成的包,就像模塊。然而,我們從類得到的自動屬性繼承搜索,支持了軟件的高層次的定製,而這是我們通過模塊和函數做不到的。

類對象提供默認行爲

執行class語句,就會得到類對象。以下是Python類主要特性:

class語句創建類對象並將其賦值給變量名。就像函數def語句,Python class語句也是可執行語句。執行時,會產生新的類對象,並將其賦值給class頭部的變量名。此外,就像def應用,class語句一般是在其所在文件導入時執行的。

class語句內的複製語句會創建類的屬性。就像模塊文件一樣,class語句內的頂層的賦值語句(不是在def之內)會產生類對象中的屬性。從技術角度來講,class語句的作用域會變成類對象的屬性的命名空間,就像模塊的全局作用域一樣。執行class語句後,類的屬性可由變量名點號運算獲取object.name

類屬性提供對象的狀態和行爲。類對象的屬性記錄狀態信息和行爲,可由這個類所創建的所有實例共享。位於類中的函數def語句會生成方法,方法將會處理實例。

實例對象是具體的元素

當調用類對象時,我們得到了實例對象。

像函數那樣調用類對象會創建新的實例對象。每次類調用時,都會建立並返回新的實例對象。實例代表了程序領域中的具體元素。

每個實例對象繼承類的屬性並獲得了自己的命名空間。由類所創建的實例對象是新命名空間。一開始是空的,但是會繼承創建該實例的類對象內的屬性。

在方法內對self屬性做賦值運算會產生每個實例自己的屬性。在類方法函數內,第一個參數(按慣例稱爲self)會引用正處理的實例對象。對self的屬性做賦值運算,會創建或修改實例內的數據,而不是類的數據。

#!/usr/bin/env python
# coding=utf-8

class FirstClass:
    def setdata(self, value):
        self.data=value
    def display(self):
        print(self.data)

x=FirstClass()
y=FirstClass()

x.setdata("King Arthur")
y.setdata(3.14)

x.display()
y.display()

x.data="New value"
x.display()


在FirstClass的setdata函數中,傳入的值會賦給self.data。在方法中,self(按慣例,這是最左側參數的名稱)會自動引用正在處理的實例(x或y),所以賦值語句會把值存儲在實例的命名空間,而不是類的命名空間。

我們可以在類的內部或外部修改實例屬性。在類內時,通過方法內對self進行賦值運算;而在類外時,則可以通過對實例對象進行賦值運算。雖然比較少見,通過在類方法函數外對變量名進行賦值運算,我們甚至可以在實例命名空間內產生全新的屬性。

類通過繼承進行定製

在Python中,實例從類中繼承,而類繼承與超類。

超類列在了類開頭的括號中。

類從其超類中繼承屬性。

實例會繼承所有可讀取類的屬性。

每個object.attribute都會開啓新的獨立搜索。Python會對每個屬性取出表達式進行對類樹的獨立搜索。這包括在class語句外對實例和類的引用(例如,X.attr),以及在類方法函數內對self實例參數屬性的引用。方法中的每個self.attr表達式都會開啓對self及其上層的類的attr屬性的搜索。

邏輯的修改是通過創建子類,而不是修改超類。在樹中層次較低的子類中重新定義超類的變量名,子類就可以取代並定製所繼承的行爲。

#!/usr/bin/env python
# coding=utf-8

class FirstClass:
    def setdata(self, value):
        self.data=value
    def display(self):
        print(self.data)

class SecondClass(FirstClass):
    def display(self):
        print('Current value = "%s"' % self.data)

z=SecondClass()
z.setdata(42)
z.display()


有時候,我們把這種在樹中較低處發生的重新定義的、取代屬性的動作稱爲重載。

類是模塊內的屬性

如果FirstClass是卸載模塊文件內,就可將其導入。單一模塊文件內可以有一個以上的類,就像模塊內其他語句,class語句會在導入時執行已定義的變量名,而這些變量名會變成獨立的模塊屬性。

#!/usr/bin/env python
# coding=utf-8

from modulename import FirstClass
class SecondClass(FirstClass):
    def display(self):
        print('Current value="%s"' % self.data)

z=SecondClass()
z.setdata(42)
z.display()

實際上,Python中的通用慣例指出,類名應該以一個大寫字母開頭,以使得他們更爲清晰。














發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章