➣ Reading Time: 8 minutes

前言

裝飾器 (decorator),可以幫助我們快速地用簡易的方式達到修飾 function 的效果,
以本篇的例子來說,我們可以替原本沒有計時功能的 function,
以一行的方式直接新增計時的功能。

範例程式碼

from functools import wraps
import time

def WongWongTimer(func):
    @wraps(func)
    def wrap(*args, **kargs):
        time_start = time.time()
        value = func(*args, **kargs)
        time_end = time.time()
        time_spend = time_end - time_start
        #print(f"[{func.__module__}.{func.__name__}] cost time: {time_spend}")
        print(f"[WongWongTimer][{func.__qualname__}] cost time: {time_spend}")

        return value

    return wrap

使用方式 – 單純版,撰寫 wongwong_utils.py

個人是存成 wongwong_utils.py 後,

要使用時,只需要在想要偵測的 function 前一行加上這個「@WongWongTimer」即可!

  • 範例如下:
from wongwong_utils import  WongWongTimer

@WongWongTimer
def test():
    print("Hello World!!!")

test()

使用方式 – 大型程式重複使用版 (放入指定資料夾並設定 __init__.py)

通常在比較大型的資料夾中,我們會將此類工具嘗試放入資料夾當中。

個人放的方法為,將上面那段程式碼存在 wongwong_utils.py 中,
並把這個檔案放在一個名為 「utils」 的資料夾當中。

參考下圖架構:

  • main.py
  • utils
    • __init__.py
    • wongwong_utils.py

我們去修改 __init__.py,更方便我們去 import 這支程式。

__init__」.py 的功能,主要是讓一個資料夾內的所有內容可以被模組化,
我們可以使用 import 資料夾名稱,來直接引入所有我們需要的、且在資料將底下的模組。

撰寫 utils 資料夾底下的 init.py (使 utils 成為 package)

from .wongwong_utils import *
__all__ = ['WongWongTimer'']

撰寫 utils 資料夾底下的 wongwong_utils.py

from functools import wraps
import time

def WongWongTimer(func):
    @wraps(func)
    def wrap(*args, **kargs):
        time_start = time.time()
        value = func(*args, **kargs)
        time_end = time.time()
        time_spend = time_end - time_start
        #print(f"[{func.__module__}.{func.__name__}] cost time: {time_spend}")
        print(f"[WongWongTimer][{func.__qualname__}] cost time: {time_spend}")

        return value

    return wrap

實作範例

from utils import WongWongTimer

@WongWongTimer
def test():
    print("Hello World!!!")

test()

因為上面已經把 utils 包裝成一份 package,
所以我們可以直接呼叫此 package 內的 WongWongTimer 模組來使用。

from utils import WongWongTimer

要使用時,只需要在想要偵測的 function 前一行加上這個「@WongWongTimer」即可!

注意:utils package 必須在「不同的資料夾」底下才可以使用。
因為被打包的 package 不包含本身
(例如說我們想在 utils 資料夾底下這樣 import WongWongTimer,會找不到不能使用)

未使用 init.py 加工成 utils package 的方法也可以

如果是一般未經過資料夾 init.py 加工的方法,我們也可以使用
from utils.wongwong_utils import WongWongTimer
可以簡記為 「from [file] import [module]」
前面的 「from utils.wongwong_utils」 代表是尋找 .py 的路徑
後面的 「import WongWongTimer」 就是要 import 的 class/function

延伸討論

有點小可惜的是,這個方便的 decorator 只能夠給 funciton 使用 (但也夠方便了),
不能給單一行程式碼使用 (需要先包進 function 當中)。