在了解完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並帶您實際了解如何運作。那,我們明天見囉!