Python 如何使用装饰器(decorators)

1. 装饰器的基本概念

装饰器是一个函数,它接受一个函数作为参数,并返回一个新的函数。装饰器可以用于在函数调用前后添加额外的功能,或者修改函数的行为。

装饰器通常通过在函数定义前使用@decorator_name语法来应用。

def decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

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

say_hello()

输出结果:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

2. 创建和使用简单装饰器

定义装饰器

一个简单的装饰器如下:

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

这个装饰器函数my_decorator接受一个函数func作为参数,并返回一个包装函数wrapper。在包装函数中,首先打印一条消息,然后调用传入的函数,最后再打印一条消息。

使用装饰器

可以使用@my_decorator语法来应用这个装饰器:

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

say_hello()

这等价于:

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

say_hello = my_decorator(say_hello)
say_hello()

3. 装饰器的嵌套

可以将多个装饰器应用于同一个函数,这称为装饰器的嵌套。装饰器的应用顺序是自下而上的,即最内层的装饰器最先应用。

def decorator1(func):
    def wrapper():
        print("Decorator 1")
        func()
    return wrapper

def decorator2(func):
    def wrapper():
        print("Decorator 2")
        func()
    return wrapper

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

say_hello()

输出结果:

Decorator 1
Decorator 2
Hello!

4. 带参数的装饰器

装饰器本身也可以接受参数。为了实现这一点,我们需要再嵌套一层函数。

创建带参数的装饰器

def repeat(num):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num):
                func(*args, **kwargs)
        return wrapper
    return decorator

使用带参数的装饰器

可以传递参数来控制装饰器的行为:

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

say_hello()

输出结果:

Hello!
Hello!
Hello!

5. 类装饰器

除了函数装饰器,Python还支持类装饰器。类装饰器是一个实现了__call__方法的类,这样的类可以像函数一样调用。

创建类装饰器

class MyDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("Something is happening before the function is called.")
        self.func(*args, **kwargs)
        print("Something is happening after the function is called.")

使用类装饰器

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

say_hello()

输出结果:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

6. 内置装饰器

Python提供了一些内置的装饰器,如@staticmethod@classmethod@property。这些装饰器常用于类的方法定义。

@staticmethod

@staticmethod用于定义静态方法,静态方法不需要访问类或实例的属性和方法。

class MyClass:
    @staticmethod
    def static_method():
        print("This is a static method.")

MyClass.static_method()

@classmethod

@classmethod用于定义类方法,类方法的第一个参数是类本身(通常命名为cls)。

class MyClass:
    @classmethod
    def class_method(cls):
        print(f"This is a class method of {cls}.")

MyClass.class_method()

@property

@property用于将方法转换为属性,以便通过属性访问方法的结果。

class MyClass:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value

obj = MyClass(42)
print(obj.value)  # 输出: 42
obj.value = 99
print(obj.value)  # 输出: 99

7. 装饰器的实际应用场景

装饰器在实际编程中有很多应用场景,下面我们列举一些常见的例子。

日志记录

装饰器可以用于记录函数的调用情况。

def log(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function {func.__name__}")
        result = func(*args, **kwargs)
        print(f"Function {func.__name__} finished")
        return result
    return wrapper

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

say_hello()

输出结果:

Calling function say_hello
Hello!
Function say_hello finished

权限检查

装饰器可以用于检查用户是否有权限执行某个操作。

def requires_permission(permission):
    def decorator(func):
        def wrapper(user, *args, **kwargs):
            if user.has_permission(permission):
                return func(user, *args, **kwargs)
            else:
                print(f"User {user.name} does not have {permission} permission.")
        return wrapper
    return decorator

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

    def has_permission(self, permission):
        return permission in self.permissions

@requires_permission("admin")
def delete_user(user):
    print(f"User {user.name} deleted.")

admin_user = User("Admin", ["admin"])
normal_user = User("User", [])

delete_user(admin_user)  # 输出: User Admin deleted.
delete_user(normal_user)  # 输出: User User does not have admin permission.

缓存

装饰器可以用于缓存函数的返回结果,以提高性能。

def cache(func):
    memo = {}
    def wrapper(*args):
        if args in memo:
            return memo[args]
        result = func(*args)
        memo[args] = result
        return result
    return wrapper

@cache
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(30))  # 输出: 832040

计时

装饰器可以用于测量函数的执行时间。

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__} took {end_time - start_time:.4f} seconds")
        return result
    return wrapper

@timer
def long_running_function():
    time.sleep(2)

long_running_function()  # 输出: Function long_running_function took 2.0001 seconds

参数校验

装饰器可以用于验证函数参数的有效性。

def validate_args(func):
    def wrapper(*args, **kwargs):
        if any(arg < 0 for arg in args):
            raise ValueError("Arguments must be non-negative")
        return func(*args, **kwargs)
    return wrapper

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

print(add(3, 5))  # 输出: 8
# print(add(-1, 5))  # 抛出异常: ValueError: Arguments must be non-negative

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值