@wraps 修飾器:讓你的 Python 代碼更加簡短可愛 | 從簡單實例來認識它

@wraps 修飾器:讓你的 Python 代碼更加簡短可愛 | 從簡單實例來認識它

咱們在上一篇文章(Python實例來認識併發與並行)中用到了 @timer ,在函數定義時,加上一個小小的 @timer ,這樣,函數執行結束後,就會自動在控制檯彙報本身運行的時間。html

好比下面這樣:python

@timer
def piper():
    for i in range(10000):
        i = i * i ** 10

piper()

輸出:
timer: using 0.00600 s

實際上,這個計時器邏輯 @timer 是咱們本身用 Python 中的修飾器特性來實現的。編程

拆解邏輯

其實咱們不用修飾器,本身也能實現計時的邏輯。併發

def piper():
    for i in range(10000):
        i = i * i ** 10

t = time.time()  # 記錄函數開始時時間
piper()
print(f"timer: using {time.time() - t :.5f} s")  # 獲取函數運行時間並打印

注意到咱們執行函數時,在其上下都包裹上了邏輯。若是咱們但願函數自帶計時邏輯,那麼爲了包住原函數,只能去新定義一個函數。app

def time_wrapper(func):
    # func 是一個函數
    t = time.time()
    func()
    print(f"timer: using {time.time() - t :.5f} s")

time_wrapper(piper)

輸出:
timer: using 0.00600 s

咱們想測試某一個函數運行時間時,將函數名輸入到 time_wrapper 裏面就好。函數

更優雅的改進

上述代碼顯然有缺點:測試

  • 咱們在編程時,心智負擔增大了;此外,代碼更冗長了
  • 若是咱們只是但願函數新增一個功能,顯然用 time_wrapper 是不行的,由於其並無改變 piper 自己

因而咱們請出今天的主角 修飾器@wrapscode

還用咱們的 timer 舉例子,咱們讓全部在 @timer 下的函數,都通過以下處理:htm

def timer(func):
    @wraps(func)
    def inner_func():
        t = time.time()
        rts = func()
        print(f"timer: using {time.time() - t :.5f} s")
        return rts
    return inner_func

piper 爲例,咱們經歷了以下變化。ip

@timer
def 原始piper():
    for i in range(10000):
        i = i * i ** 10

實際上,當你再調用 piper 時,你的 piper 內部邏輯早已變爲:

def 當前piper():
    t = time.time()
    rts = 原始piper()
    print(f"timer: using {time.time() - t :.5f} s")
    return rts

總結

本文簡單與讀者朋友們「科普」一下修飾器,注意到咱們這裏實際上僅僅修飾了無參數的函數。其實,修飾器還有許多更加優雅用途,好比傳入參數 *args, **kwargs ,修飾類 __call__ 等用法。期待之後我遇到好的應用場景,將經驗分享給朋友們。

記得點個『在看』!

我是小拍,關注我!

相關文章
相關標籤/搜索