Python編程思想(24):類的實例方法

李寧老師已經在「極客起源」 微信公衆號推出《Python編程思想》電子書,囊括了Python的核心技術,以及Python的主要函數庫的使用方法。讀者可以在「極客起源」 公衆號中輸入 160442 開始學習。

《Python編程思想》總目錄

《Python編程思想》專欄

對於在類中定義的實例方法,Python會自動綁定方法的第1個參數(通常是self),第1個參數總是指向調用該方法的對象。由於實例方法(包括構造方法)的self參數會自動綁定,因此程序在調用普通實例方法、構造方法時不需要爲第1個參數傳值。

self參數最大的作用就是引用當前方法的調用者,比如在構造方法中通過self爲該對象增加實例變量。也可以在一個實例方法中訪問該類的另一個實例方法或變量。假設定義了一個Bird類,這個Bird對象的move()方法需要調用它的fly()方法,此時就可通過self參數作爲 fly()方法的調用者。

方法的第1個參數所代表的對象是不確定的,但它的類型是確定的。它所代表的只能是當前類的實例;只有當這個方法被調用時,它所代表的對象才被確定下來。也就是說,誰在調用這個方法,方法的第1個參數就代表誰。

例如定義如下Bird類:

class Bird:
    # 定義一個fly()方法
    def fly(self):
        print("正在執行fly方法")
    # 定義一個move()方法,move()方法需要藉助fly()方法
    def move(self):
        # 使用self參數引用調用fly()方法的對象
        self.fly()
        print("正在執行move方法")

bird = Bird()
bird.move()

上面代碼的move()方法中的self代表該方法的調用者,誰在調用move()方法,那麼self就代表誰。因此該方法表示當一個Bird對象調用move()方法時,move()方法需要依賴它自己的 fly()方法。

在現實世界裏,對象的一個方法依賴另一個方法的情形很常見,例如,喫飯方法依賴拿筷子或刀叉的方法,寫程序方法依賴敲鍵盤方法,這種依賴都是同一個對象的兩個方法之間的依賴。

當 Python對象的一個方法調用另一個方法時,不能省略self。也就是說,將上面的move方法改爲如下形式是不正確的。

def move(self):
    # 省略self,下面的代碼會報錯
    fly()
    print("正在執行move方法")

此外,在構造方法中,self參數(第1個參數)代表該構造方法正在初始化的對象。例如如下代碼。

class SelfInConstructor :
    def __init__(self) :
        # 在構造方法裏定義一個name變量(局部變量)
        name = 'Bill'
        # 使用self代表該構造方法正在初始化的對象
        # 下面的代碼將會把該構造方法正在初始化的對象的name實例變量設爲Mike
        self.foo = 'Mike'
# 所有使用SelfInConstructor創建的對象的name實例變量將被設爲Mike
print(SelfInConstructor().foo) # 輸出Mike

在 SelfInConstructor的構造方法中,self參數總是引用該構造方法正在初始化的對象。程序中的代碼將正在執行初始化的SelfInConstructor對象的name實例變量設爲Mike,這意味着該構造方法返回的所有對象的name實例變量都等於Mike。

需要說明的是,自動綁定的self參數並不依賴具體的調用方式,不管是以方法調用還是以函數調用的方式執行它,self參數一樣可以自動綁定。例如如下程序:

示例代碼:self_demo.py

class Product:
    def process(self):
        print('self參數: ', self)
        
product = Product()
# 以方法形式調用process()方法
product.process() # <__main__.User object at 0x00000000021F8240
# 將User對象的test方法賦值給foo變量
process = product.process
# 通過process變量(函數形式)調用process()方法。
process() # <__main__.User object at 0x00000000021F8240

上面程序中的代碼以方法形式調用Product對象的 process方法,此時方法調用者當然會自動綁定到方法的第1個參數(self參數)。接下來以函數形式調用Product對象的process方法,看上去此時沒有調用者了,但程序依然會把實際調用者綁定到process函數的第1個參數,因此上面程序的輸出結果完全相同。

當self參數作爲對象的默認引用時,程序可以像訪問普通變量一樣來訪問這個self參數,甚至可以把self參數當成實例方法的返回值。看下面程序。

示例代碼:return_self.py

class Person :
    def speed_up(self):
        if hasattr(self, 'speed'):
            self.speed += 1
        else:
            self.speed = 20
        # return self返回調用該方法的對象
        return self
person = Person()
# 可以連續調用同一個方法
person.speed_up().speed_up().speed_up().speed_up()
print("speed:", person.speed)

從上面程序中可以看出,如果在某個方法中把self參數作爲返回值返回,則可以多次連續調用同一個方法,從而使得代碼更加簡潔。但是這種把self參數作爲返回值的方法可能會造成實際意義的模

糊,例如上面的speed_up方法用於表示的速度的增加,也就是speed屬性值加1,實際上不應該有返回值。也就是說,儘管使用self參數作爲方法的返回值可以讓代碼更加簡潔,但可能造成實際意義的模糊,所以這種方式要謹慎使用。

-----------------支持作者請轉發本文,也可以加李寧老師微信:unitymarvel,或掃描下面二維碼加微信--------

歡迎關注  極客起源  微信公衆號,更多精彩視頻和文章等着你哦!

 

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