您好,登錄后才能下訂單哦!
這篇文章主要介紹python如何使用類來實現裝飾器,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
嘗試用類來實現裝飾器
絕大多數裝飾器都是基于函數和 閉包 實現的,但這并非制造裝飾器的唯一方式。事實上,Python 對某個對象是否能通過裝飾器(@decorator)形式使用只有一個要求:decorator 必須是一個“可被調用(callable)的對象。
# 使用 callable 可以檢測某個對象是否“可被調用” >>> def foo(): pass ... >>> type(foo) <class 'function'> >>> callable(foo) True
函數自然是“可被調用”的對象。但除了函數外,我們也可以讓任何一個類(class)變得“可被調用”(callable)。辦法很簡單,只要自定義類的 __call__ 魔法方法即可。
class Foo: def __call__(self): print("Hello, __call___") foo = Foo() # OUTPUT: True print(callable(foo)) # 調用 foo 實例 # OUTPUT: Hello, __call__ foo()
基于這個特性,我們可以很方便的使用類來實現裝飾器。
下面這段代碼,會定義一個名為 @delay(duration) 的裝飾器,使用它裝飾過的函數在每次執行前,都會等待額外的 duration 秒。同時,我們也希望為用戶提供無需等待馬上執行的 eager_call 接口。
import time import functools class DelayFunc: def __init__(self, duration, func): self.duration = duration self.func = func def __call__(self, *args, **kwargs): print(f'Wait for {self.duration} seconds...') time.sleep(self.duration) return self.func(*args, **kwargs) def eager_call(self, *args, **kwargs): print('Call without delay') return self.func(*args, **kwargs) def delay(duration): """裝飾器:推遲某個函數的執行。同時提供 .eager_call 方法立即執行 """ # 此處為了避免定義額外函數,直接使用 functools.partial 幫助構造 # DelayFunc 實例 return functools.partial(DelayFunc, duration) 如何使用裝飾器的樣例代碼: @delay(duration=2) def add(a, b): return a + b # 這次調用將會延遲 2 秒 add(1, 2) # 這次調用將會立即執行 add.eager_call(1, 2)
@delay(duration) 就是一個基于類來實現的裝飾器。當然,如果你非常熟悉 Python 里的函數和閉包,上面的 delay 裝飾器其實也完全可以只用函數來實現。所以,為什么我們要用類來做這件事呢?
與純函數相比,我覺得使用類實現的裝飾器在特定場景下有幾個優勢:
? 實現有狀態的裝飾器時,操作類屬性比操作閉包內變量更符合直覺、不易出錯
? 實現為函數擴充接口的裝飾器時,使用類包裝函數,比直接為函數對象追加屬性更易于維護
? 更容易實現一個同時兼容裝飾器與上下文管理器協議的對象
以上是“python如何使用類來實現裝飾器”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。