在了解完Python的基本語法與功用後,今日我們將要來探討Python中的函式修飾器,因為在後續有關網頁的flask中會使用到該方法,提前了解之後便能更好上手!
怕各位仍不太熟悉Python的函式,在此先做一個範向您展示:
def sum(a,b):
    result = float(a)+float(b)
    return result
sum(8,7)
上面的程式碼,是Python最一般的function範例 ── 一個將傳入數值相加的function。
一個Python的函式都具有傳入值、回傳值,以及執行的動作。
在介紹函式修飾器前,我們要提到function的基本屬性。
如果我們為function添加了type()函式,會發現,其實funtion也是一個物件:
def sum(a,b):
    result = float(a)+float(b)
    return result
print(type(sum))

所以我們便可以利用此屬性,將function當作傳入值去代入至別的function的裡面,並執行:
def func():
	print("this is a function!")
def wrapper(function):
	function()
wrapper(func)
那最後wrapper的輸出結果,理所當然地便是:this is a function!
而我們也可以在function裡面寫入function:
def function_generator():
	def new_func():
		print("new函式發動")
	return new_func
test = function_generator()  
test()

詳細流程解釋如下:
這些程式碼執行的過程為:
**test()**
test 是甚麼?它是由 function_generator() 回傳的 **new_func()**new_func() 發動:print(”new函式發動”)
new函式發動
不過,當我們每次寫個函式,要執行某事件時,腦迴路都要一直繞來繞去,實在是有夠麻煩的 ── 因此,Python中出現了函式修飾器的語法!
def decoratorTest(func):
    def wrapper():
        print("start")
        func()
        print("end")
    return wrapper
@decoratorTest #函式修飾器發威!
def hello():
    print("Hello")
hello()

上圖是兩個功能相同的程式,然而,右圖的程式碼是不是比較簡潔呢?
做個小總結,所以Python的函式修飾器是甚麼?
函式修飾器是一個工具,允許您在不修改原始函式程式碼的情況下動態地改變或擴展函式,以便新增或添加額外的功能。
python函式修飾器的優點:
我們也可以對函式修飾器代入數值,以執行不同的結果。
下方的範例便是將程式執行的次數代入至修飾器內,已達成輸出幾次結果的範例:
def decoratorTest(times):
    def decorator(func):
        def wrapper():
            print("start")
            for i in range(times):
                func()
            print("end")
        return wrapper
    return decorator
@decoratorTest(5) #執行五次
def hello():
    print("Hello")
hello()

如果說我們最主要的 hello() 函式也要傳入值,那我們在函式修飾器裡執行這條函式時,也必須要代入這些數值,否則便會出現錯誤。
也因此,我們需要在wrapper內寫入 *args,**kwargs 語法,並把變數代入至函式內執行:
def decoratorTest(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print("start")
            for i in range(times):
                func(*args, **kwargs)
            print("end")
        return wrapper
    return decorator
@decoratorTest(5)
def hello(name):
    print("Hello, " + name)
hello("John")

這裡介紹一下甚麼是 *args & **kwargs:
***args** 和 **kwargs 是Python中的特殊語法,用於處理函式的可變參數。它能讓您傳遞不定數量的位置參數和關鍵字參數給一個函式。
讓我們分別解釋它們的作用:
***args**(星號引數):
***args** 是一個特殊的參數,它允許您將不定數量的位置參數傳遞給一個函式。***args** 會將這些位置參數打包成一個元組(tuple)。def print_args(*args):
    for arg in args:
        print(arg)
print_args(1, 2, 3, 4)  # 輸出:1 2 3 4
****kwargs**(雙星號關鍵字引數):
**kwargs 是另一個特殊的參數,它允許您傳遞不定數量的關鍵字參數(帶有名稱的參數)給一個函式。**kwargs 會將這些關鍵字參數打包成一個字典(dictionary)。def print_kwargs(**kwargs):
    for key, value in kwargs.items():
        print(key, value)
print_kwargs(a=1, b=2, c=3)  # 輸出:a 1  b 2  c 3
其中一個常見的用法便是在函式定義中結合使用 *args 和 **kwargs,這樣可以接受任意數量的位置參數和關鍵字參數,好譬如:
def example_function(arg1, arg2, *args, kwarg1="default", **kwargs):
    # arg1 和 arg2 是必要的位置參數
    # *args 接受任意數量的其他位置參數,存為元組
    # kwarg1 是一個有默認值的關鍵字參數
    # **kwargs 接受任意數量的其他關鍵字參數,存為字典
    pass
這種方式能夠使函式更具彈性,能夠處理各種參數組合,同時保持可讀性。
from time import sleep,time
def getTime(func):
    def wrapper():
        start = time()
        func()
        print("執行時間:",time()-start)
    return wrapper
def decoratorTest(func):
    def wrapper():
        print("start")
        sleep(1)
        func()
        print("end")
    return wrapper
@getTime
@decoratorTest
def hello():
    print("hello")
hello()

from time import sleep,time
def getTime(func):
    def wrapper():
        start = time()
        func()
        print("執行時間:",time()-start)
    return wrapper
def decoratorTest(times):
    def decorator(func):
        def wrapper():
            print("start")
            for _ in range(times):
                sleep(1)
                func()
            print("end")
        return wrapper
    return decorator
@getTime
@decoratorTest(5)
def hello():
    print("hello")
hello()

以上,都是我們修飾器大概的基礎原理了,是不是非常燒腦呢?
仍是不太理解的話,其實沒關係,先對這些東西有個大概的概念即可。因為在Flask中我們也不會用到這麼難的函式修飾器,等真的在某些專案中實際碰到了,再去深入瞭解即可。
那今天的Python函式修飾器教學便到此結束,明天我們終於要回歸正題,重返網頁的領域,接觸Flask並帶您實際了解如何運作。那,我們明天見囉!