Python 装饰器详解

装饰器是 Python 中一种强大的语法特性,它允许在不修改原函数代码的情况下动态地扩展函数的功能。装饰器本质上是一个高阶函数,它接受一个函数作为参数并返回一个新的函数。

基本装饰器

1. 简单装饰器示例

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

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

say_hello()

输出:

复制代码
函数执行前
Hello!
函数执行后

2. 装饰器的工作原理

  • @my_decorator 语法糖等价于 say_hello = my_decorator(say_hello)
  • my_decorator 接收 say_hello 函数作为参数
  • 返回 wrapper 函数,它"包裹"了原函数

带参数的装饰器

1. 函数带参数的装饰器

python 复制代码
def decorator_with_args(func):
    def wrapper(name):
        print(f"准备调用 {func.__name__}")
        func(name)
        print(f"{func.__name__} 调用完成")
    return wrapper

@decorator_with_args
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

2. 装饰器本身带参数

python 复制代码
def repeat(num_times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Bob")

输出:

复制代码
Hello, Bob!
Hello, Bob!
Hello, Bob!

类装饰器

装饰器不仅可以是函数,还可以是类:

python 复制代码
class CountCalls:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0

    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print(f"函数已被调用 {self.num_calls} 次")
        return self.func(*args, **kwargs)

@CountCalls
def example():
    print("执行示例函数")

example()
example()
example()

输出:

复制代码
函数已被调用 1 次
执行示例函数
函数已被调用 2 次
执行示例函数
函数已被调用 3 次
执行示例函数

多个装饰器叠加

可以同时应用多个装饰器:

python 复制代码
def uppercase_decorator(func):
    def wrapper():
        result = func()
        return result.upper()
    return wrapper

def exclamation_decorator(func):
    def wrapper():
        result = func()
        return result + "!"
    return wrapper

@exclamation_decorator
@uppercase_decorator
def say_hi():
    return "hi there"

print(say_hi())  # 输出: HI THERE!

注意:装饰器的应用顺序是从下往上,先应用 uppercase_decorator,然后是 exclamation_decorator

内置装饰器

Python 本身提供了一些内置装饰器:

  1. @staticmethod - 定义静态方法
  2. @classmethod - 定义类方法
  3. @property - 将方法转换为属性

装饰器的常见用途

  1. 日志记录
  2. 性能测试(计算函数执行时间)
  3. 权限验证
  4. 缓存(备忘录模式)
  5. 输入验证
  6. 注册插件
  7. 重试机制

性能测试装饰器示例

python 复制代码
import time

def timer(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(2)

slow_function()

保留原函数的元信息

使用 functools.wraps 可以保留原函数的元信息:

python 复制代码
from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """这是包装函数的文档字符串"""
        print("装饰器添加的功能")
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def example():
    """这是原函数的文档字符串"""
    print("原函数功能")

print(example.__name__)  # 输出: example
print(example.__doc__)   # 输出: 这是原函数的文档字符串

总结

装饰器是 Python 中非常强大的特性,它:

  • 允许在不修改原函数代码的情况下扩展功能
  • 遵循开放-封闭原则(对扩展开放,对修改封闭)
  • 使代码更加模块化和可重用
  • 常用于日志、性能测试、权限控制等场景

掌握装饰器可以让你写出更加优雅和高效的 Python 代码。

相关推荐
数据智能老司机2 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机3 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机3 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机3 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i4 小时前
drf初步梳理
python·django
每日AI新事件4 小时前
python的异步函数
python
这里有鱼汤5 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook14 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室14 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三16 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试