Python装饰器


Python中的 装饰器(decorator) 是一种用于修改函数或类行为的函数。它们允许我们在不修改原函数的情况下,动态地增加功能,通常用于日志记录、性能测试、权限验证等。装饰器本质上是高阶函数,即接受一个函数作为参数并返回一个新的函数。

装饰器的基本原理

装饰器本质上是一个闭包(closure),它将目标函数包裹在一个函数内部,然后通过调用装饰器返回的函数来执行新的行为。通过这种方式,我们可以在不改变目标函数的情况下增强其功能。

最简单的装饰器例子
def my_decorator(func):
    def wrapper():
        print("在函数执行之前做一些事情")
        func()
        print("在函数执行之后做一些事情")
    return wrapper

# 使用装饰器
@my_decorator
def say_hello():
    print("Hello, World!")

say_hello()

输出:

在函数执行之前做一些事情
Hello, World!
在函数执行之后做一些事情
原理分析
  1. my_decorator 是一个装饰器,它接受一个函数 func 作为参数。
  2. wrapper 是内部定义的函数,负责在目标函数前后添加额外的逻辑。
  3. 使用 @my_decorator 语法糖相当于 say_hello = my_decorator(say_hello),即 say_hello 现在指向 wrapper 函数。
  4. say_hello() 被调用时,实际执行的是 wrapper() 函数,它在目标函数 say_hello() 前后插入了额外的逻辑。

带参数的装饰器

有时我们希望装饰器能够接受额外的参数,比如记录日志时可以指定日志级别,这时我们可以让装饰器函数接受参数。

带参数的装饰器例子
def my_decorator_with_args(message):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(f"装饰器参数:{message}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

# 使用装饰器,传递参数
@my_decorator_with_args("这是一个装饰器参数")
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Alice")

输出:

装饰器参数:这是一个装饰器参数
Hello, Alice!
原理分析
  1. my_decorator_with_args 接受参数 message 并返回一个装饰器函数 decorator
  2. decorator 接受目标函数 func 并返回一个包装函数 wrapper,该包装函数在执行目标函数之前输出装饰器参数。
  3. @my_decorator_with_args("这是一个装饰器参数") 是通过传参的方式动态生成装饰器,并应用到 say_hello 上。

通用装饰器

装饰器经常需要应用于带有参数的函数,Python 提供了 *args**kwargs 来捕获任意数量的位置和关键字参数,以便装饰器通用性更强。

示例:处理带有参数的函数
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

result = add(3, 5)
print(f"结果是: {result}")

输出:

函数执行之前
函数执行之后
结果是: 8

Python内置装饰器

Python 提供了几个内置的装饰器,最常见的包括:

  • @property:将类方法转化为属性。
  • @staticmethod:将类方法变为静态方法,不需要 self 参数。
  • @classmethod:将类方法的第一个参数变为类本身 (cls),而不是实例。
@property 示例
class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value <= 0:
            raise ValueError("半径必须大于0")
        self._radius = value

circle = Circle(5)
print(circle.radius)  # 使用属性
circle.radius = 10    # 设置新值
print(circle.radius)

输出:

5
10

装饰器的嵌套(多个装饰器)

多个装饰器可以通过多个 @ 来嵌套使用,装饰器的执行顺序是从内向外的。

示例
def decorator1(func):
    def wrapper(*args, **kwargs):
        print("执行decorator1")
        return func(*args, **kwargs)
    return wrapper

def decorator2(func):
    def wrapper(*args, **kwargs):
        print("执行decorator2")
        return func(*args, **kwargs)
    return wrapper

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

greet("Bob")

输出:

执行decorator1
执行decorator2
Hello, Bob!

总结

  • 装饰器 是修改函数或类行为的一种简洁方式,允许你在不改变原代码的情况下增强功能。
  • 装饰器可以通过 @ 来简化代码,并且支持传递参数和嵌套。
  • Python 中有许多内置装饰器,如 @property@staticmethod@classmethod,让类的定义更为灵活。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值