Python 装饰程序运行错误:";UnboundLocalError:局部变量';计数';作业前参考“;

Python 装饰程序运行错误:";UnboundLocalError:局部变量';计数';作业前参考“;,python,decorator,Python,Decorator,我在两个不同的装饰器中创建了两个变量,其中一个装饰器工作正常,但另一个显示错误 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

我在两个不同的装饰器中创建了两个变量,其中一个装饰器工作正常,但另一个显示错误

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:赋值前引用的局部变量“count”


据我所知,这两种功能遵循相同的模式。在这两个decorator中,都在decorator中定义了一个变量,并在包装器函数中使用该变量。但是,这个
foo
函数工作得很好,但是这个
boo
函数不工作。我想知道原因是什么?

区别在于,在第一个示例中,名称
data
总是指同一个对象;它永远不会被重新分配。所引用的字典
数据
本身发生了变异(更改),但它始终是同一个对象

相反,在第二个示例中执行
count+=1
时,会更改名称
count
引用的值。这使得
count
成为一个局部变量。当解释器看到这一点时,它会注意到您在分配给它之前引用了局部变量
count
,并且失败

解决方案是通过声明
非本地

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