1. 程式人生 > >Python從入門到放棄(五):類細講

Python從入門到放棄(五):類細講

Ⅰ.入門

一:編寫基礎

1.類與例項(他們在python中都是物件)

類提供預設行為,是例項的工廠
例項是程式處理的實際物件:各自有獨立的名稱空間,但是繼承類中的變數名。
類來自語句宣告,例項來自呼叫。
類和例項都是物件,並且是兩種不同的物件型別.

2.最基本建立過程

語法模板:

class 類名:
    語句1
    語句2
    。 。 。
    語句n

例1:
這裡寫圖片描述
這裡寫圖片描述

解釋:
    class建立類物件並且將其賦值給變數名(建立了類並且賦值給了FristClass
    Class內的頂層賦值語句(不是在def裡面建立的)會建立類的屬性(包括函式名和一些變數)
.類屬性提供物件的狀態和行為。
像函式那樣呼叫類物件回建立新的例項物件。每次類呼叫的時候,都會建立並且返回新的例項物件.例項物件代表程式領域中的具體物件,每個例項物件繼承類的屬性並且獲得自己的名稱空間。 方法中對self屬性做賦值運算會產生每個例項自己的屬性。(就像上面的setData函式中產生了新的data屬性一樣),但是在使用的時候必須先賦值,就像上面先呼叫setData函式之後才能呼叫show(),不然會錯誤。同時,也是建立修改的例項物件中的資料,而不是類中的資料. 每個例項擁有自己的屬性,但是共用類的方法 類通常是通過對self引數進行賦值運算從而建立例項的所有屬性的。就像上面data的出現,但是不是必須如此。程式可以取出,修改,或建立其所引用的任何物件的屬性。(這裡是c++學習不一樣的地方)

例2:
這裡寫圖片描述
這裡寫圖片描述

總結:
    類屬性是在類的頂層語句中建立的.例項中並不會有類中的屬性,但是例項會通過繼承搜尋來找到他的建立它的類中的這個屬性.(這就是我們說繼承的原因,很像一些東西被繼承下來一樣,事實上只是向上搜尋罷了)
    例項中def方法建立的(簡單來說可以這麼理解.)屬性就成為例項本身自己的屬性.而且可以不通過內建函式訪問.可以直接建立一個例項中的屬性.
    在編寫類方法的時候,二話不說,方法前面的第一個引數加上self. self是正確處理例項的一個重要引數,所以必須要帶上去.

3.類繼承

前面是類和例項之間的關係,那麼這裡就是類和子類之間的關係.
自然界是層次的,那麼類之間也能夠是層次的.在較低的層次重寫一些屬性,實現特殊需要的子類.
例項從類中繼承,而子類繼承於超類.


繼承語法模板:

class 類名(要繼承的類名):
    語句1
    語句2
    。。。
    語句n

例子:
這裡寫圖片描述
這裡寫圖片描述

解釋:
    被繼承的那個類放在宣告的括號中就行了
    子類從父類中繼承屬性。當讀取(使用)子類屬性的時候,若是它並不存在與子類中,python會自動搜尋這個屬性。例項會繼承所有可讀取類的屬性。先是搜尋自己,然後搜尋建立自己的類,然後搜尋其類的超類.直到找到或者找不到.
    在子類中show()的方法進行了重寫,就會覆蓋繼承的父類的show()方法。但是父類中的show()方法並不會改變(只是定製而不影響),我們把這種在樹的較低處發生的重新定義的,取代屬性的動作叫做過載.

注意:
    對於類和模組的關係,要是一個類是寫在了一個模組內部的,我們直到class實際上是執行一些程式碼塊並且返回一個類物件賦給類名.比如上面的class FirstClass就是後面被賦予的變數名.同樣,載入一個寫了類的模組也像普通的那樣載入.
    比如,我的模組名叫做test.py,裡面有一個類叫做Leo,則載入方式有
    from test import Leo
    X=Leo()
    .......
    或者
    import test
    X=test.Leo()
    ......

4.運算子過載初步

例子:
這裡寫圖片描述
這裡寫圖片描述

解釋:
    當新的例項構造的時候,會呼叫__init__,__init__相當於c++中的建構函式,但是概念要更加簡單。
    當LastClss例項出現在+表示式中的時候,會呼叫__add__,使用__add__能夠通過過載直接處理兩個物件的+運算問題
    當列印一個物件的時候(從技術上來講,當通過str內建函式或者python內部的等價形式來將其轉化為列印字串的時候),呼叫__str__.對於print,python把要列印的物件傳遞給__str__中的self,該方法返回的字串看作是物件的列印字串。於是,使用__str__,我們可以直接用print來顯示一個物件而不是通過一個其他的函式.
    其他的運算子過載方式同上.
    從上面知道LastClass繼承了SecondClass,所以會繼承secondclass的show方法,所以上面輸出的時候顯示的是use second。。。。

5.令人疑惑的例子(重要)

這裡寫圖片描述
這裡寫圖片描述

“`
解釋:
首先,leo類中沒有新增任何東西,pass語句表示什麼也不做
利用前面講的性質手動新增屬性(這時候類裡面有name和age兩個屬性)
這個時候例項本身沒有屬性,例項對於類的繼承也是搜尋上面的類.,所以,在沒有改變之前,就連值都還是類中的值。但是某一個例項改變屬性值的時候,它便有了自己的屬性.同時不會影響到上層的類的屬性.因此,這個時候,x有了自己name屬性,但是y依然需要從類中來找.
先打個預防針:本質上面,名稱空間物件的屬性都是以字典的形式來實現的,而類繼承樹只是連線其他字典的字典而已.(很抽象,之後會詳細討論)
dict屬性是針對大多數基於類的物件的名稱空間字典(注意:leo有自己的name,age。X也有自己的name,但是y什麼也沒有,因為y沒有賦值改變的操作。所以只會搜尋到它的類中去找
class指出連線的類.bases指出一個類的超類.
最後的那部分說明,方法或是什麼並不僅僅侷限在一個class中,也可以在外部建立,然後賦值連線到類的內部也是一樣可以的.這些都顯示了Python的靈活性.
對於新手的建議就是老老實實的把一些方法什麼的規規矩矩的寫在類的內部,先練習好基本的格式,然後再擴充套件到動態.

二:類建立詳細步驟

通過一個關於人事管理的程式,下面講建立一個實際可用的類需要的基本步驟

版本一:

這裡寫圖片描述
結果
這裡寫圖片描述

步驟1:建立例項

1.構思類的功能和性質,應該得到一個什麼樣的類
2.想好在這個類中應當有的屬性(在c++中被稱為成員變數)
3.構造一個好的建構函式(這裡有個地方注意,對於預設引數,當前一個引數為預設引數後,後面的所有引數必須規定為預設引數)
這裡寫圖片描述

步驟2:新增行為方法

1.有成員變數是不夠的,還要構思這個類能夠有什麼樣的行為
2.對構思好的行為編寫成員函式
這裡寫圖片描述

步驟3:運算子過載

根據需要過載運算子使運算更加貼近自己編寫的類,其實這步可要可不要.
這裡寫圖片描述

步驟4:通過子類定製行為

這裡寫圖片描述
1.類方法總是可以在一個例項中呼叫(通常都可以這麼做,Python把該例項自動地發給self引數)Instance.method(args…..)
2.或者通過類來呼叫(較少使用,其中我們必須要手動的傳遞例項進去)
Class.method(instance,args…..)

Ⅱ.放棄