[Python基礎]淺談裝飾器 decorator

2024/01/24閱讀時間約 4 分鐘

當你想讓原本函式新增其他功能,又不想更動原本函式時,Python提供了一種強大而靈活的工具,那就是裝飾器。

但對於新手來說這個裝飾器,非常抽象難以理解,讓我們繼續往下看,慢慢的抽絲剝繭吧。

在 Python 中,使用@當做裝飾器使用的語法糖符號 ( 語法糖指的是將複雜的程式碼包裝起來的糖衣,也就是簡化寫法 )。

本文範例皆在Colab上執行。

裝飾器基本架構:

  1. 定義裝飾器函式 decorator_name
def decorator_name(func):
def wrapper(*args, **kwargs):
# 在呼叫原始函式之前的額外操作
result = func(*args, **kwargs)
# 在呼叫原始函式之後的額外操作
return result
return wrapper # 返回內部定義的函式

其中:

  • decorator_name 是裝飾器的名稱。
  • func 是被裝飾的原始函式。
  • return result 可以將該返回值保留下來,使得裝飾器不會影響到原始函數的返回結果。
  • wrapper 是一個內層函式,回傳自己內部的函式是裝飾器的標準用法。
  1. 在被裝飾的函式上應用裝飾器:
@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)
raw-image

當你調用 my_function(1, 2) 時,實際上執行的是 wrapper 函數。

wrapper 函數首先輸出 "在呼叫原始函式之前的額外操作",

然後呼叫原始函數 my_function(1, 2)

再輸出 "在呼叫原始函式之後的額外操作"。

最後,x 被賦值為 my_function 的返回值(1 + 2),在print(x)印出3。


最後我們來試著修改一下 把裝飾器函式內的return result註解掉看看。

如圖下,x就會是一個None的值,因為少了return result所以沒有把原始函式的值保留下來。

raw-image

其他應用

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 秒

總結好處

程式碼重複使用 :

裝飾器允許你將一些通用的行為應用到多個函式上,從而實現程式碼的重用。這樣你就不需要在每個函式中重複相同程式碼

模組化:

裝飾器使得程式碼更具模組性,更易於維護。你可以定義各種裝飾器,每個都執行不同的功能,然後在需要的地方應用這些裝飾器。

清晰可讀的程式碼: 使用裝飾器可以使程式碼更加清晰可讀。它允許你將與函式相關非核心邏輯提取出來,使得函數本身的目的更為明確。


大家一起讓自己程式碼越來越簡潔明瞭吧~

49會員
87內容數
Python程式設計師,不是在學習就是在學習的路上
留言0
查看全部
發表第一個留言支持創作者!