装饰器 #

装饰器是一种修改函数行为的优雅方式。

一、基本概念 #

装饰器本质上是一个函数,它接受一个函数作为参数并返回一个新函数。

python
def my_decorator(func):
    def wrapper():
        print("函数执行前")
        func()
        print("函数执行后")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
# 输出:
# 函数执行前
# Hello!
# 函数执行后

二、带参数的装饰器 #

python
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("函数执行前")
        result = func(*args, **kwargs)
        print("函数执行后")
        return result
    return wrapper

@my_decorator
def add(a, b):
    return a + b

print(add(3, 5))  # 输出:函数执行前, 函数执行后, 8

三、保留函数元信息 #

python
from functools import wraps

def my_decorator(func):
    @wraps(func)  # 保留原函数的元信息
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def greet(name):
    """问候函数"""
    print(f"Hello, {name}!")

print(greet.__name__)  # "greet"(不是"wrapper")
print(greet.__doc__)   # "问候函数"

四、带参数的装饰器 #

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

@repeat(times=3)
def say_hello():
    print("Hello!")

say_hello()  # 输出3次Hello!

五、常见应用场景 #

5.1 计时装饰器 #

python
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)
    return "完成"

slow_function()  # slow_function 执行时间:1.0001秒

5.2 日志装饰器 #

python
def log(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"调用 {func.__name__},参数:{args}, {kwargs}")
        result = func(*args, **kwargs)
        print(f"{func.__name__} 返回:{result}")
        return result
    return wrapper

@log
def add(a, b):
    return a + b

add(3, 5)

5.3 缓存装饰器 #

python
from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(50))  # 快速计算

5.4 权限检查 #

python
def require_login(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if not is_logged_in():
            raise PermissionError("请先登录")
        return func(*args, **kwargs)
    return wrapper

@require_login
def get_user_data():
    return "敏感数据"

六、类装饰器 #

python
class CountCalls:
    def __init__(self, func):
        self.func = func
        self.count = 0
    
    def __call__(self, *args, **kwargs):
        self.count += 1
        print(f"第{self.count}次调用")
        return self.func(*args, **kwargs)

@CountCalls
def say_hello():
    print("Hello!")

say_hello()  # 第1次调用
say_hello()  # 第2次调用

七、多个装饰器 #

python
@decorator1
@decorator2
def func():
    pass

# 等价于
func = decorator1(decorator2(func))

八、总结 #

概念 说明
本质 接受函数返回函数的函数
语法 @decorator
参数 使用*args, **kwargs
元信息 使用@wraps(func)保留
带参数 多层嵌套函数
最后更新:2026-03-16