计数调用装饰器:为何要将inner.call_count重置为0?
装饰器计数器初始化问题解析
问题背景
以下是用于统计函数调用次数的装饰器代码:
from functools import wraps def counting_calls(func): @wraps(func) def inner(*args, **kwargs): inner.call_count += 1 return func(*args, **kwargs) inner.call_count = 0 return inner
测试代码:
@counting_calls def add(a: int, b: int) -> int: '''return sum of 2 ints''' return a + b print(add(10, b=20)) print(add(30, 5)) print(add(3, 5)) print(add(4, 5)) print('num calls =', add.call_count) print(add(11, 5)) print('num calls =', add.call_count)
疑问:为何要设置inner.call_count = 0?这一操作是否会导致call_count始终被重置为0,无法保存总调用次数?
解答
初始化
inner.call_count = 0的必要性:
这是为闭包函数inner创建并初始化一个计数器属性。如果不做这一步,第一次调用被装饰后的函数时,执行inner.call_count += 1会直接抛出AttributeError——因为此时inner还没有call_count这个属性,Python无法对一个不存在的属性做自增操作。不会出现反复重置的问题:
inner.call_count = 0只在装饰目标函数的瞬间执行一次。当你用@counting_calls装饰add时,counting_calls函数会被调用一次,生成对应的inner函数,初始化它的call_count为0,之后add变量就指向了这个inner函数。后续每次调用add,都是直接调用这个已经初始化好的inner,只会执行inner.call_count += 1来累加次数,不会再回到counting_calls函数里重新设置call_count为0。
从测试代码的运行结果也能直观验证:
30 35 8 9 num calls = 4 16 num calls = 5
可以看到call_count是持续累加的,完全能正常统计总调用次数。
内容的提问来源于stack exchange,提问作者ERJAN
相关产品推荐
相关产品推荐

