我在两个不同的装饰器中创建了两个变量,一个装饰器工作正常,但另一个显示错误。
def running_average(func):
data = {'total': 0, 'count': 0}
def wrapper(*args, **kwargs):
print(data)
val = func(*args, **kwargs)
data['total'] += val
data['count'] += 1
print('Average of {} so far: {:.01f}'.format(func.__name__,
data['total']/data['count']))
return func(*args, **kwargs)
return wrapper
@running_average
def foo(x):
return x + 2
这个 foo 函数有效。
def countcalls(func):
count = 0
print(count)
def wrapper(*args, **kwargs):
print(count)
count += 1
print('# of calls: {}'.format(count))
return func(*args, **kwargs)
return wrapper
@countcalls
def boo(x):
return x + 2
但是这个boo
函数显示错误:UnboundLocalError: local variable 'count' referenced before assignment
.
根据我的理解,这两个函数遵循相同的模式。在这两个装饰器中,装饰器中都定义了一个变量,并且该变量在包装函数中使用。然而,这foo
功能运行良好,但是这个boo
功能不起作用。我想知道这是什么原因?
不同之处在于,在第一个示例中,名称data
总是指同一个对象;它永远不会被重新分配。词典data
指的是本身发生变异(改变),但它始终是同一个对象。
相反,当你这样做时count += 1
在第二个示例中,这会更改名称的值count
指。这使得count
局部变量。当解释器看到这一点时,它会注意到您引用了局部变量count
在分配给它之前,并且失败。
解决方案是告诉解释器使用count
通过声明它来从封闭范围中nonlocal
def countcalls(func):
count = 0
print(count)
def wrapper(*args, **kwargs):
nonlocal
print(count)
count += 1
print('# of calls: {}'.format(count))
return func(*args, **kwargs)
return wrapper
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)