gpt4 book ai didi

python - 将修改后的状态传递给外部嵌套装饰器

转载 作者:太空宇宙 更新时间:2023-11-03 11:37:09 25 4
gpt4 key购买 nike

嵌套两个存储和更改状态信息的 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

最佳答案

您可以将带有结果的字典设置为包装器,该字典将在装饰器之间共享:

import functools
import time

def time_this(func):
@functools.wraps(func)
def wrapper(*args, **kwargs) :
time1 = time.time()
rtn_val = func(*args, **kwargs)
time2 = time.time()
wrapper.results['time_this'] += (time2 - time1) * 1000.0
return rtn_val

results = getattr(wrapper, 'results', {})
results['time_this'] = 0
setattr(wrapper, 'results', results)

return wrapper

def count_calls(func):
@functools.wraps(func)
def wrapper(*args, **kwargs) :
rtn_val = func(*args, **kwargs)
wrapper.results['count_calls'] = wrapper.results['count_calls'] + 1
return rtn_val

results = getattr(wrapper, 'results', {})
results['count_calls'] = 0
setattr(wrapper, 'results', results)

return wrapper


@time_this
@count_calls
def my_func():
print("Hello World!")

for i in range(10):
my_func()

print(my_func.results)
print('avg:', my_func.results['time_this'] / my_func.results['count_calls'])

打印:

Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
{'count_calls': 10, 'time_this': 0.03719329833984375}
avg: 0.003719329833984375

关于python - 将修改后的状态传递给外部嵌套装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57065099/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com