Python 裝飾器(Decorators)入門教學 | Python

2026/04/24

Python 中,裝飾器(Decorators) 是一個非常強大且優雅的語法特性。它能讓你在不修改原始函式程式碼的情況下,為函式添加額外的功能。本篇將帶你從基礎概念開始,逐步掌握裝飾器的使用方法。

什麼是裝飾器?

裝飾器本質上是一個 函式,它接受另一個函式作為參數,並回傳一個新的函式。這個概念建立在 Python 中「函式是一等公民(First-Class Object)」的基礎上,也就是函式可以被當作變數傳遞、作為參數傳入其他函式。

# 裝飾器的基本結構
def my_decorator(func):
    def wrapper():
        print("函式執行前")
        func()
        print("函式執行後")
    return wrapper

使用 @ 語法

Python 提供了 @ 語法糖來簡化裝飾器的使用。以下兩種寫法是等價的:

# 方法一:手動套用
def say_hello():
    print("Hello!")

say_hello = my_decorator(say_hello)

# 方法二:使用 @ 語法糖(推薦)
@my_decorator
def say_hello():
    print("Hello!")

say_hello()
# 輸出:
# 函式執行前
# Hello!
# 函式執行後

處理函式參數

實際開發中,被裝飾的函式通常會有參數。我們可以使用 *args**kwargs 來處理任意數量的參數:

from functools import wraps

def my_decorator(func):
    @wraps(func)  # 保留原函式的名稱與文件字串
    def wrapper(*args, **kwargs):
        print(f"呼叫函式:{func.__name__}")
        result = func(*args, **kwargs)
        print("函式執行完畢")
        return result
    return wrapper

@my_decorator
def greet(name, greeting="你好"):
    print(f"{greeting}, {name}!")

greet("Alice")
# 輸出:
# 呼叫函式:greet
# 你好, Alice!
# 函式執行完畢

這裡使用了 functools.wraps,它能保留被裝飾函式的原始資訊(如 __name____doc__),這是撰寫裝飾器時的最佳實踐。

實用範例:計時裝飾器

裝飾器最常見的應用之一是測量函式的執行時間:

import time
from functools import wraps

def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} 執行時間:{end - start:.4f} 秒")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(1)
    print("完成!")

slow_function()
# 輸出:
# 完成!
# slow_function 執行時間:1.0012 秒

帶參數的裝飾器

有時候我們希望裝飾器本身也能接受參數,這需要再多包一層函式:

from functools import wraps

def repeat(n):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(n):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def say(message):
    print(message)

say("Hello!")
# 輸出:
# Hello!
# Hello!
# Hello!

@repeat(3) 會先呼叫 repeat(3) 取得真正的裝飾器,再將 say 函式傳入該裝飾器。

內建裝飾器

Python 本身也提供了幾個常用的內建裝飾器,在物件導向程式設計中經常使用:

class MyClass:
    @staticmethod      # 靜態方法,不需要 self 或 cls 參數
    def static_method():
        print("這是靜態方法")

    @classmethod       # 類別方法,第一個參數為 cls
    def class_method(cls):
        print(f"這是 {cls.__name__} 的類別方法")

    @property          # 將方法變為屬性存取
    def name(self):
        return self._name

總結

裝飾器是 Python 中非常實用的功能,它讓你能以簡潔的方式為函式添加額外行為。核心概念是:裝飾器接收一個函式、回傳一個增強後的函式。記得使用 @wraps 保留原函式資訊,並善用 *args**kwargs 處理任意參數。常見應用包括日誌記錄、效能計時、權限驗證等。希望這篇文章能幫助你掌握這個強大的 Python 語法特性。

裝飾器的基礎是函式,建議先閱讀 Python 函數(Functions)入門指南。想進一步了解內建裝飾器在類別中的應用,可以參考 Python 的物件導向程式設計