Python修饰器

装饰器(Decorator)是Python中一种强大的语法特性,它允许你在不修改原函数代码的情况下,为函数添加额外的功能。装饰器本质上是一个高阶函数,它接受一个函数作为参数,并返回一个新的函数。

一、装饰器基础

1. 最简单的装饰器示例

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

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

say_hello()

输出:

函数执行前
Hello!
函数执行后

 

2. 装饰器的工作原理

使用@decorator语法糖等同于:

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

say_hello = my_decorator(say_hello)  # 手动装饰
say_hello()

二、带参数的函数装饰器

1. 装饰带参数的函数

def decorator(func):
    def wrapper(*args, **kwargs):
        print(f"准备调用 {func.__name__}")
        result = func(*args, **kwargs)
        print(f"{func.__name__} 调用完成")
        return result
    return wrapper

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

greet("Alice")

 2. 装饰器本身带参数

def repeat(num_times):
    def decorator(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 greet(name):
    print(f"Hello, {name}!")

greet("Bob")

三、类装饰器

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

1. 类作为装饰器

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 say_hello():
    print("Hello!")

say_hello()
say_hello()

 2. 带参数的类装饰器

class DecoratorWithArgs:
    def __init__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
    
    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print(f"装饰器参数: {self.args}, {self.kwargs}")
            return func(*args, **kwargs)
        return wrapper

@DecoratorWithArgs(1, 2, debug=True)
def test_func(x, y):
    return x + y

print(test_func(10, 20))

四、内置装饰器

Python提供了一些有用的内置装饰器:

1. @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("半径不能为负")
        self._radius = value

c = Circle(5)
print(c.radius)  # 5
c.radius = 10
print(c.radius)  # 10

 2. @classmethod 和 @staticmethod

class MyClass:
    class_attr = "类属性"
    
    def __init__(self, value):
        self.value = value
    
    @classmethod
    def class_method(cls):
        print(f"访问类属性: {cls.class_attr}")
    
    @staticmethod
    def static_method():
        print("这是一个静态方法")

MyClass.class_method()  # 访问类属性: 类属性
MyClass.static_method()  # 这是一个静态方法

3. @functools.wraps

解决装饰器导致的元信息丢失问题:

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """包装函数文档"""
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def example():
    """示例函数文档"""
    pass

print(example.__name__)  # 输出 'example' 而不是 'wrapper'
print(example.__doc__)   # 输出 '示例函数文档' 而不是 '包装函数文档'

五、装饰器的高级用法

1. 多个装饰器叠加

def decorator1(func):
    def wrapper():
        print("装饰器1 - 前")
        func()
        print("装饰器1 - 后")
    return wrapper

def decorator2(func):
    def wrapper():
        print("装饰器2 - 前")
        func()
        print("装饰器2 - 后")
    return wrapper

@decorator1
@decorator2
def hello():
    print("Hello!")

hello()

 输出:

装饰器1 - 前
装饰器2 - 前
Hello!
装饰器2 - 后
装饰器1 - 后

2. 装饰器缓存(Memoization) 

from functools import lru_cache

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

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

 3. 权限检查装饰器

def requires_admin(func):
    def wrapper(user, *args, **kwargs):
        if not user.is_admin:
            raise PermissionError("需要管理员权限")
        return func(user, *args, **kwargs)
    return wrapper

class User:
    def __init__(self, name, is_admin=False):
        self.name = name
        self.is_admin = is_admin

@requires_admin
def delete_database(user):
    print(f"{user.name} 正在删除数据库...")

admin = User("Alice", is_admin=True)
regular = User("Bob")

delete_database(admin)  # 正常工作
delete_database(regular)  # 抛出PermissionError

六、装饰器的实际应用场景

  1. 日志记录:自动记录函数调用和参数

  2. 性能测试:测量函数执行时间

  3. 权限验证:检查用户权限

  4. 缓存:存储函数结果避免重复计算

  5. 事务处理:数据库操作前开始事务,操作后提交或回滚

  6. 输入验证:检查函数参数有效性

  7. 重试机制:函数失败时自动重试

  8. API路由:Web框架中的路由注册

七、总结

Python装饰器是一种强大的元编程工具,它能够:

  • 在不修改原函数代码的情况下扩展功能

  • 保持代码干净和可复用

  • 实现横切关注点(如日志、权限等)的集中管理

  • 通过组合装饰器创建复杂行为

理解装饰器是掌握Python高级编程的重要一步,它广泛应用于Web框架(如Flask、Django)、测试框架和各种库中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值