Python装饰器完全指南 - 来自Python Cheatsheet项目的深度解析

Python装饰器完全指南 - 来自Python Cheatsheet项目的深度解析

python-cheatsheet All-inclusive Python cheatsheet python-cheatsheet 项目地址: https://gitcode.com/gh_mirrors/pyt/python-cheatsheet

什么是Python装饰器

Python装饰器是一种强大的语法特性,它允许开发者在不修改原始函数或类代码的情况下,为其添加额外的功能。装饰器本质上是一个高阶函数,它接受一个函数作为参数并返回一个新的函数。这种设计模式遵循了"开放封闭原则" - 对扩展开放,对修改封闭。

基础装饰器实现

让我们从最简单的装饰器开始:

def simple_decorator(func):
    def wrapper():
        print("函数执行前操作")
        func()
        print("函数执行后操作")
    return wrapper

@simple_decorator
def greet():
    print("你好,世界!")

greet()

输出结果:

函数执行前操作
你好,世界!
函数执行后操作

这个例子展示了装饰器的基本结构:

  1. 定义一个装饰器函数simple_decorator,它接受一个函数func作为参数
  2. 在装饰器内部定义一个包装函数wrapper
  3. 在包装函数中添加额外的功能,并调用原始函数
  4. 返回包装函数

处理带参数的函数

实际开发中,我们经常需要装饰带参数的函数。这时可以使用*args**kwargs来接收任意数量的位置参数和关键字参数:

def param_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"准备执行函数 {func.__name__}")
        result = func(*args, **kwargs)
        print(f"函数 {func.__name__} 执行完毕")
        return result
    return wrapper

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

print(add(3, 5))

输出结果:

准备执行函数 add
函数 add 执行完毕
8

保留函数元信息

使用装饰器后,原始函数的元信息(如__name____doc__等)会被包装函数覆盖。为了解决这个问题,Python提供了functools.wraps装饰器:

from functools import wraps

def preserve_meta(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """包装函数的文档字符串"""
        return func(*args, **kwargs)
    return wrapper

@preserve_meta
def example():
    """原始函数的文档字符串"""
    pass

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

带参数的装饰器

有时候我们需要装饰器本身也能接受参数。这种情况下,我们需要在装饰器外再包装一层函数:

from functools import wraps

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

@repeat(num_times=3)
def say_hello(name):
    print(f"你好,{name}!")

say_hello("张三")

输出结果:

你好,张三!
你好,张三!
你好,张三!

类装饰器

装饰器不仅可以作用于函数,还可以作用于类。类装饰器的实现方式与函数装饰器类似:

def class_decorator(cls):
    class WrappedClass(cls):
        def __init__(self, *args, **kwargs):
            print("类实例化前操作")
            super().__init__(*args, **kwargs)
            print("类实例化后操作")
    return WrappedClass

@class_decorator
class MyClass:
    def __init__(self, value):
        self.value = value
        print("原始初始化")

obj = MyClass(42)

输出结果:

类实例化前操作
原始初始化
类实例化后操作

类作为装饰器

Python还允许使用类来实现装饰器,这种方式特别适合需要维护状态的场景:

class CallCounter:
    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)

@CallCounter
def say_hi(name):
    print(f"你好,{name}")

say_hi("李四")
say_hi("王五")

输出结果:

这是第 1 次调用
你好,李四
这是第 2 次调用
你好,王五

装饰器的实际应用场景

  1. 日志记录:自动记录函数调用信息
  2. 性能测试:测量函数执行时间
  3. 权限验证:检查用户权限
  4. 缓存:实现函数结果的缓存
  5. 重试机制:在失败时自动重试
  6. 输入验证:验证函数参数的有效性

装饰器的最佳实践

  1. 尽量使用functools.wraps保留原始函数元信息
  2. 保持装饰器的单一职责,每个装饰器只做一件事
  3. 避免过度使用装饰器,以免降低代码可读性
  4. 为装饰器编写清晰的文档说明
  5. 考虑装饰器的性能影响,特别是在高频调用的函数上

通过掌握Python装饰器,你可以编写出更加模块化、可重用和可维护的代码。装饰器是Python高级编程中的重要工具,合理使用可以大幅提升代码质量和开发效率。

python-cheatsheet All-inclusive Python cheatsheet python-cheatsheet 项目地址: https://gitcode.com/gh_mirrors/pyt/python-cheatsheet

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗琰锴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值