python基礎教程:__call__用法
阿新 • • 發佈:2022-04-18
__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方法,所以我們直接用子類的例項作為可呼叫物件