天天看點

第7.14節 Python類中的執行個體方法詳析

第7.14節 Python類中的執行個體方法詳析

一、    執行個體方法的定義

在本章前面章節已經介紹了類的執行個體方法,執行個體方法的定義有三種方式:

1.    類體中定義執行個體方法

第一種方式很簡單,就是在類體中定義,所有在類中定義的方法預設是執行個體方法。定義執行個體方法與定義函數基本相同,隻是Python要求執行個體方法的第一個形參必須為self,也就是執行個體對象本身,是以執行個體方法至少應該有一個self參數。關于self的說明,請大家參考老猿前面的章節《​​第7.5節 揭開Python類中self的面紗​​》。如下例子:

class MethodTest():
    def method1(self):print("in method1")      

2.    在類體外将一個函數直接指派給一個對象執行個體

Python 是動态語言,允許為對象動态增加方法,相關步驟如下:

1)    按照執行個體方法定義形式在類體外定義一個函數,函數需要将self作為第一個參數;

2)    使用“執行個體對象名.方法名=函數”方式在執行個體中增加方法。

老猿認為,這種動态定義執行個體方法,本質上就是動态增加執行個體變量,隻是這個執行個體變量比較特殊,是個函數類型,對應的指派也是一個函數。是以上述方法定義的執行個體方法,與類體中定義的方法還是有差别的,對這種方法Python 不會将執行個體對象自動綁定到方法的第一個參數,即使将第一個參數命名為 self 也沒有用。

3.    在類體外将一個函數綁定到對象執行個體

這種方法與第二種方法本質上是一緻的,隻是能解決調用時無法自動将執行個體對象作為第一個實參處理的問題。具體綁定方法如下:

2)    使用“執行個體對象名.方法名 = MethodType(函數, 對象)” 方式在執行個體中增加方法。

其中MethodType是從Python的types子產品import進來的,通過MethodType可以将函數與執行個體對象的某個方法進行綁定,調用時就無需再傳遞執行個體對象到第一個參數。

上述第二種和第三種方法都是動态方法,綁定的“執行個體對象名.方法名”可以是一個已經存在的執行個體方法,也可以是新定義的一個屬性方法,如果是一個已經存在的執行個體方法,新綁定的函數将替換原執行個體的方法。

二、    執行個體方法的使用

1.    執行個體方法可以在類體的執行個體方法内調用,此時調用方使用“self.方法”方式調用,并在調用傳遞實參時不需要使用self。請看如下類的定義和調用:

class MethodTest():
    def method1(self):print("in method1")
    def method2(self):
        print("in method2")
        self.method1()      

上述代碼中method2調用了方法method1,使用self方式調用。

2.    在類體外面調用類體内直接定義的執行個體方法,直接用“執行個體名.方法名”方式調用,對于類體内定義的執行個體方法傳實參時無需傳遞self形參對應的實參,由Python在編譯時自動添加執行個體對象作為第一個實參。請看上面的類定義執行個體對象後調用method2:

m1=MethodTest()
m1.method2()      

上述樣例代碼執行截圖:

第7.14節 Python類中的執行個體方法詳析

注意:在類外調用執行個體方法時,無需也不能傳遞self的實參,由Python解釋器自動為其在後面執行時添加。如果定義的方法沒有以類方法的方式定義,也沒有在方法定義時将self作為第一個形參,編譯時并不會報錯,但調用該執行個體方法時會有運作時錯誤,因為Python會強行綁定執行個體對象作為第一個參數,是以調用者的實參與定義的形參是一樣時,此時會多出一個實參self,導緻執行時報參數個數不對的錯誤。

3.    在類體外面調用通過函數直接指派定義的執行個體方法時,其調用方式與類體内定義的模式不同,要求第一個實參必須是調用的對象本身;

以上面的類MethodTest為例,如果要增加一個method3的執行個體方法,其代碼如下:

def dynamicmethond(self):print("in DynamicMethond")
m1.method3=dynamicmethond      

這樣m1這個執行個體就增加了一個method3方法,調用代碼如下:

m1.method3(m1)  #注意必須在第一個參數将執行個體自身傳遞進去

4.    在類體外面調用通過MethodType綁定的執行個體方法時,其調用方式與類體内定義的模式相同,第一個形參self對應的實參無需傳值,由Python自動添加對應的執行個體對象;

以上面的類MethodTest為例,如果要增加一個method4的執行個體方法進行綁定,其代碼如下:

def dynamicmethond(self):print("in DynamicMethond")
m1.method4= MethodType(dynamicmethond,m1)      

這樣m1這個執行個體就增加了一個method4方法,且實作了方法與執行個體的綁定,調用代碼如下:

m1.method4()      

三、    構造方法

之是以單獨介紹構造方法,是因為構造方法是一個特殊的執行個體方法,具體特殊性包括如下:

1.    Python的構造方法對所有自定義類名字都固定為__init__,且第一個參數必須為self;

2.    可以允許開發者沒有在類中定義構造方法,此時Python 會自動為該類定義一個隻包含一個 self 參數的預設的構造方法;

3.    構造方法如果有多個形參,除了第一個參數必須是self外,其他參數都是建立執行個體時在類名後面的括号中給出,也就構造方法的參數就是建立執行個體時傳入的參數,也必須是建立執行個體時傳入;

4.    構造方法是每個執行個體定義時自動執行;

5.    在子類重寫構造方法時,必須調用超類(繼承的類)的構造方法,否則可能無法正确地初始化對象。

1)    Python3中所有類都繼承于object類,構造函數的重寫不用考慮object類的情況,即無需調用object類的構造函數;

2)    在構造方法中調用父類的構造方法時,可以使用“父類.類名.__init__(self,其他參數)”的方式調用;

3)    在構造方法中調用父類的構造方法時,可以使用“super().__init__ (參數)”的方式調用,注意此時的參數中不能傳遞self參數。但這種情況如果存在多個超類時,執行的是第一個超類的構造方法,其實參必須按照第一個超類構造方法的形參來傳遞,其他超類的構造方法必須通過“父類.類名.__init__(self,其他參數)”的方式調用。

了解了這幾點,結合其他語言的構造方法,就了解了Python的構造方法。

四、    本節相關代碼的完整執行截屏

第7.14節 Python類中的執行個體方法詳析

本節結合案例詳細介紹了執行個體方法的定義和使用方法,需要注意,動态定義執行個體方法隻影響單個執行個體自身,對其他執行個體沒有影響。老猿認為動态定義執行個體方法的使用範圍比較有限,如果可能盡量使用類體定義執行個體方法,僅在特定場景(如動态擴充功能)下使用動态執行個體方法。