當你想讓原本函式新增其他功能,又不想更動原本函式時,Python提供了一種強大而靈活的工具,那就是裝飾器。
但對於新手來說這個裝飾器,非常抽象難以理解,讓我們繼續往下看,慢慢的抽絲剝繭吧。
在 Python 中,使用「@
」當做裝飾器使用的語法糖符號 ( 語法糖指的是將複雜的程式碼包裝起來的糖衣,也就是簡化寫法 )。
本文範例皆在Colab上執行。
裝飾器基本架構:
decorator_name
:def decorator_name(func):
def wrapper(*args, **kwargs):
# 在呼叫原始函式之前的額外操作
result = func(*args, **kwargs)
# 在呼叫原始函式之後的額外操作
return result
return wrapper # 返回內部定義的函式
其中:
decorator_name
是裝飾器的名稱。func
是被裝飾的原始函式。return result
可以將該返回值保留下來,使得裝飾器不會影響到原始函數的返回結果。wrapper
是一個內層函式,回傳自己內部的函式是裝飾器的標準用法。@decorator_name
def my_function():
# 函式內容
讓我們往下看程式範例來更了解裝飾器吧~
# 步驟1: 定義裝飾器函數
def decorator_name(func):
def wrapper(*args, **kwargs):
print('在呼叫原始函式之前的額外操作')
result = func(*args, **kwargs)
print('在呼叫原始函式之後的額外操作')
return result
return wrapper # 返回內部定義的函式
# 步驟2: 在被裝飾的函數上應用裝飾器
@decorator_name
def my_function(a,b):
print(a+b)
return a + b
# 調用被裝飾的
x = my_function(1,2)
print(x)
當你調用 my_function(1, 2)
時,實際上執行的是 wrapper
函數。
wrapper
函數首先輸出 "在呼叫原始函式之前的額外操作",
然後呼叫原始函數 my_function(1, 2)
,
再輸出 "在呼叫原始函式之後的額外操作"。
最後,x
被賦值為 my_function
的返回值(1 + 2
),在print(x)
印出3。
最後我們來試著修改一下 把裝飾器函式內的return result
註解掉看看。
如圖下,x
就會是一個None的值,因為少了return result
所以沒有把原始函式的值保留下來。
CT時間計算
import time
def performance_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 執行時間:{end_time - start_time} 秒")
return result
return wrapper
@performance_decorator
def slow_function():
time.sleep(2)
print("Function executed")
slow_function()
# 輸出內容
# Function executed
# slow_function 执行时间:2.0056798458099365 秒
程式碼重複使用 :
裝飾器允許你將一些通用的行為應用到多個函式上,從而實現程式碼的重用。這樣你就不需要在每個函式中重複相同的程式碼。
模組化:
裝飾器使得程式碼更具模組性,更易於維護。你可以定義各種裝飾器,每個都執行不同的功能,然後在需要的地方應用這些裝飾器。
清晰可讀的程式碼: 使用裝飾器可以使程式碼更加清晰和可讀。它允許你將與函式相關的非核心邏輯提取出來,使得函數本身的目的更為明確。