1. 程式人生 > 其它 >python基礎教程:__call__用法

python基礎教程:__call__用法

__call__可以使得方法變成可被呼叫物件;(PS:python中的方法和普通函式有點區別:方法的第一個引數是類例項)

允許一個類的例項像函式一樣被呼叫。實質上說,這意味著 x() 與 x.call() 是相同的。注意__call__引數可變。這意味著你可以定義__call__為其他你想要的函式,無論有多少個引數。

class Entity:
'''呼叫實體來改變實體的位置'''

def _init_(self,size,x,y):
	self.x,self.y = x,y
	self.size = size
def _call_(self,x,y):
	'''改變實體的位置'''
	self.x, self.y = x,y
	
e = Entity(1,2,3)#建立例項
e(4,5)#例項可以像函式那樣執行,並傳入x y值,修改物件的x y

例項物件也可以像函式一樣作為可呼叫物件來用,那麼,這個特點在什麼場景用得上呢?

這個要結合類的特性來說,類可以記錄資料(屬性),而函式不行(閉包某種意義上也可行),利用這種特性可以實現基於類的裝飾器,在類裡面記錄狀態,比如,下面這個例子用於記錄函式被呼叫的次數:

class Counter:
	def _init_(self,func):
		self.func = func
		self.count = 0
	
	def _call_(self,*args,**kwargs):
		self.count += 1
		return self.func(*args,**kwargs)

@Counter
def foo():
	pass
for i in range(10):
	foo()

print(foo.count) #10

Python大型免費公開課,適合初學者入門
點選此處加群免費獲取學習資料及必備軟體。

首先這裡的@Counter是裝飾器,執行起來順序是 foo = Counter(foo),例項化,把foo函式傳到類Counter裡面,並存到物件屬性裡面,然後返回foo = Counter例項。

這時foo已經是Counter例項,而不是本身foo函式。

PS:__call__這種用法在pytorch中也有所體現,pytorch中自定義的類繼承於nn.Module父類,且該子類中對父類的forward方法進行了過載,且父類nn.Module中的__call__中呼叫了forward方法,所以我們直接用子類的例項作為可呼叫物件