李寧老師已經在「極客起源」 微信公衆號推出《Python編程思想》電子書,囊括了Python的核心技術,以及Python的主要函數庫的使用方法。讀者可以在「極客起源」 公衆號中輸入 160442 開始學習。
《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,或掃描下面二維碼加微信--------
歡迎關注 極客起源 微信公衆號,更多精彩視頻和文章等着你哦!