[python3] 装饰器
装饰器是Python中一种特殊的语法,用于在不修改原函数代码的情况下,为函数添加额外的功能。
- 装饰器基于函数闭包和函数作为第一类对象的特性实现。
-
原理:
- Python中的装饰器本质上是一个函数或类,它接受一个函数作为参数,并返回一个新的函数(或类)。
- 装饰器通过在原函数周围包裹一层额外的逻辑来修改函数的行为,比如添加日志、缓存、权限验证等功能。
-
设计:
- 装饰器通常使用函数定义来实现,也可以使用类来实现(类装饰器)。
- 装饰器函数需要接受被装饰的函数作为参数,并返回一个新的函数。
- 装饰器函数内部通常定义一个嵌套函数,用于对原函数进行包装,可以在嵌套函数中添加额外的逻辑。
- 装饰器可以有多个,多个装饰器会按照从上到下的顺序依次进行装饰。
-
使用:
- 使用装饰器时,可以使用
@装饰器函数
的语法将装饰器应用于目标函数。 - 装饰器可以直接放置在目标函数定义的上方,会自动将目标函数作为参数传递给装饰器函数,并将返回的新函数赋值给目标函数名。
- 也可以通过
目标函数 = 装饰器函数(目标函数)
的方式手动应用装饰器。
- 使用装饰器时,可以使用
-
注意事项:
- 装饰器会修改原函数的行为,因此在使用装饰器时要注意不要破坏原函数的预期功能。
- 装饰器只在函数定义阶段执行一次,之后每次调用被装饰的函数,实际上是调用装饰器返回的新函数。
- 装饰器可以接受参数,可以使用带有参数的装饰器来实现更灵活的功能增强。
- 装饰器在一些框架和库中广泛应用,如Flask中的路由装饰器、Django中的身份验证装饰器等。
下面是几种生成装饰器的代码示例:
- 简单的函数装饰器:
def simple_decorator(func):def wrapper(*args, **kwargs):print("Before calling the function")result = func(*args, **kwargs)print("After calling the function")return resultreturn wrapper@simple_decorator
def greet(name):print(f"Hello, {name}")greet("Alice")
- 接受参数的函数装饰器:
def parametrized_decorator(prefix):def decorator(func):def wrapper(*args, **kwargs):print(f"{prefix}: Before calling the function")result = func(*args, **kwargs)print(f"{prefix}: After calling the function")return resultreturn wrapperreturn decorator@parametrized_decorator("LOG")
def add(a, b):return a + bresult = add(3, 4)
print(result)
- 类装饰器:
class ClassDecorator:def __init__(self, func):self.func = funcdef __call__(self, *args, **kwargs):print("Before calling the function")result = self.func(*args, **kwargs)print("After calling the function")return result@ClassDecorator
def multiply(x, y):return x * yresult = multiply(3, 5)
print(result)
多个装饰器
当一个函数被多个装饰器装饰时,装饰器的调用顺序是从下往上的,也就是从最靠近目标函数的装饰器开始执行,然后依次向外层装饰器执行,直到最外层的装饰器为止。这样的执行顺序确保了每个装饰器都能按照正确的顺序影响函数的行为。
下面是一个示例,演示了一个函数被多个装饰器装饰时的执行顺序:
def decorator1(func):def wrapper(*args, **kwargs):print("Decorator 1 - Before calling the function")result = func(*args, **kwargs)print("Decorator 1 - After calling the function")return resultreturn wrapperdef decorator2(func):def wrapper(*args, **kwargs):print("Decorator 2 - Before calling the function")result = func(*args, **kwargs)print("Decorator 2 - After calling the function")return resultreturn wrapper@decorator1
@decorator2
def example_func(message):print(f"Function executed with message: {message}")example_func("Hello, World!")
在上面的示例中,example_func
函数被decorator1
和decorator2
两个装饰器装饰。根据装饰器执行顺序的原则,首先会执行decorator2
,然后再执行decorator1
,最后才执行原始的example_func
函数。因此,输出的结果会按照装饰器的嵌套顺序依次打印出相应的信息。
请记住,装饰器的执行顺序对于最终函数的行为可能会产生重要影响,因此在设计和使用装饰器时,务必注意装饰器的顺序以及各个装饰器之间的交互。