python 装饰器装饰递归函数如何只装饰一遍
时间: 2024-08-30 18:02:15 浏览: 153
在Python中,装饰器是一种设计模式,可以让你修改或者增强函数的行为,而无需修改函数本身的代码。然而,当装饰器应用于递归函数时,可能会遇到一个问题:装饰器会在每次递归调用时都执行一次,这可能导致性能下降或不必要的重复工作。
为了避免这种情况,你可以通过以下方法来实现只装饰一遍的功能:
1. 使用闭包和函数属性:通过在装饰器内部定义一个闭包函数,并在第一次调用时将其赋值给被装饰函数的一个属性。这样,即使递归发生多次,装饰器代码也只会执行一次。
2. 利用functools.wraps:使用`functools.wraps`装饰器来确保装饰器的元数据被正确复制到包装函数上,并且可以使用一个标记来检查是否已经装饰过。
下面是一个使用闭包和函数属性来装饰递归函数的例子:
```python
def once_decorator(func):
def wrapper(*args, **kwargs):
if hasattr(func, "decorated"):
# 如果函数已经被装饰过,则直接调用原函数
return func(*args, **kwargs)
else:
# 装饰函数
setattr(func, "decorated", True)
# 执行装饰逻辑(例如,打印日志等)
print(f"Decorating {func.__name__}")
# 执行原函数
return func(*args, **kwargs)
return wrapper
@once_decorator
def recursive_function(n):
if n == 0:
return 1
else:
return n * recursive_function(n - 1)
# 第一次调用
result = recursive_function(5)
# 第二次调用,装饰器只会执行一次
another_result = recursive_function(5)
```
在这个例子中,`recursive_function`会被装饰一次,而不管它递归调用多少次。`wrapper`函数检查`func`是否有`decorated`属性,如果有,就直接返回原函数的结果;如果没有,就在第一次调用时设置该属性,并执行装饰逻辑。
阅读全文