2022年10月23日 星期日

[Python] Decorator 裝飾器 (1)

最近發現自己在 Python上的技巧需要提升,雖然以前就知道 Decorator的概念,但我在
實際應用上很少使用,趁此機會來重新理解下。

Decorator簡單來說,是一種 function,並以另一個 function作為輸入,用來擴充輸入
function的功能。

以下面程式碼為例:

def hello_alice(hello_func):
    hello_func("Alice")

def say_hello(name):
    print (f"Hello {name}")

if __name__ == '__main__':
    hello_alice(say_hello)

Output:

Hello Alice

這裡 hello_alice使用 say_hello當作參數傳入, hello_alice就是作為 say_hello
decorator。


Syntactic Sugar

通常 decorator會使用更簡潔的語法糖 "@"包裝,使用上面的範例修改:

def hello_alice(hello_func):
    hello_func("Alice")

@hello_alice
def say_hello(name):
    print (f"Hello {name}")

if __name__ == '__main__':
    say_hello

Output:

Hello Alice

@hello_alice代表將 say_hello當作參數傳入 hello_alice function。


Inner Functions

Python的 function也能夠在另一個 function中被定義,稱為 inner function。inner function可以
讓 decorator的使用更加靈活:

def greet(func):

    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result

    return wrapper

@greet
def say_hello(name):
    print(f"Hello {name}")

if __name__ == '__main__':
    say_hello("Alice")
    say_hello("Bob")

Output:

Hello Alice
Hello Bob

其中 wrapper就是作為 decorator @greet的 inner function。 並且會使用 *args**kwargs來接收參數。


Example - Measure Time

一個 decorator經典的範例是用於測量 function執行所花的時間:

import time

def measuretime(func):

    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print (func.__name__, end - start)
        return result

    return wrapper

@measuretime
def count_down(n):
    while n > 0:
        n -= 1

if __name__ == '__main__':
    count_down(500000)

count_down 0.018976449966430664

使用 decorator @measure的來測量 count_down function所花費的時間。

沒有留言:

張貼留言