【发布时间】:2019-07-16 20:38:45
【问题描述】:
当嵌套两个存储和更改状态信息的 Python 装饰器时,将内部装饰函数的状态传递给外部装饰器的最佳方式是什么?
例如,我们可能有由
定义的装饰器def time_this(func):
@functools.wraps(func)
def wrapper(*args, **kwargs) :
start = time.process_time()
rtn_val = func(*args, **kwargs)
wrapper.time_taken = time.process_time() - start
return rtn_val
return wrapper
def count_calls(func):
@functools.wraps(func)
def wrapper(*args, **kwargs) :
wrapper.num_calls += 1
return func(*args, **kwargs)
wrapper.num_calls = 0
return wrapper
然后我们可以如下装饰一个函数
@time_this
@count_calls
def my_func():
time.sleep(0.5)
print("Hello World!")
但是,如果我们再尝试
my_func()
print(my_func.time_taken)
print(my_func.num_calls)
我们得到的输出是
Hello World!
0.5007079059998887
0
(注意num_calls属性始终为0。)
为了澄清,我完全理解为什么会发生这种情况,但我想找出解决这个问题的最佳方法是什么(这样上面的代码就可以做到你希望的那样,并且更新包装器中的num_calls)。
【问题讨论】:
-
运行后计数不应该为零
-
另外,你可能想要交换装饰器的顺序,除非你想计时计数增量。
-
@JohnDoe。请运行您发布的代码。这就是 MCVE 的全部意义所在。我们必须谈论同一个实际的事情,而不是我猜你的意思。
-
我无法运行代码。在
num_calls上获取一个AttributeError,无论它是否带有functools。顺便说一下,我把它改成了wraps -
对 functools 不太熟悉,但我找到了this section,我猜这就是他想要的