简体   繁体   English

装饰器运行错误:“UnboundLocalError:赋值前引用了局部变量‘count’”

[英]Decorator running error: "UnboundLocalError: local variable 'count' referenced before assignment"

I created two variables inside two different decorators, and one decorator works good but the other one shows an error.我在两个不同的装饰器中创建了两个变量,一个装饰器运行良好,但另一个显示错误。

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

This foo function works.这个 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

But this boo function shows error: UnboundLocalError: local variable 'count' referenced before assignment .但是这个boo函数显示错误: UnboundLocalError: local variable 'count' referenced before assignment

From my understanding, these two functions follow the same pattern.根据我的理解,这两个函数遵循相同的模式。 In both decorators, a variable is defined in the decorator, and the variable is used in the wrapper function.在两个装饰器中,都在装饰器中定义了一个变量,在包装函数中使用了该变量。 However, this foo function works good, but this boo function doesn't work.但是,这个foo函数很好用,但是这个boo函数不起作用。 I was wondering what is the reason?我想知道是什么原因?

The difference is that in the first example, the name data always refers to the same object;不同的是,在第一个例子中,名称data总是指向同一个对象; it is never reassigned.它永远不会被重新分配。 The dictionary data refers to is itself mutated (changed), but it is always the same object.字典data所指的本身是变异(改变)的,但它始终是同一个对象。

In contrast, when you do count += 1 in your second example, that changes the value that the name count refers to.相反,当您在第二个示例中执行count += 1时,会更改名称count所指的值。 That makes count a local variable.这使得count成为局部变量。 When the interpreter sees this, it notices that you reference the local variable count before assigning to it, and fails.当解释器看到这一点时,它注意到您在分配给它之前引用了局部变量count ,并失败了。

The solution is to tell the interpreter to use the count from the enclosing scope by declaring it nonlocal解决方案是通过将其声明nonlocal来告诉解释器使用来自封闭范围的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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 UnboundLocalError:赋值前引用的局部变量'error' - UnboundLocalError: local variable 'error' referenced before assignment UnboundLocalError: 赋值前引用的局部变量错误 - UnboundLocalError: local variable referenced before assignment error Python:UnboundLocalError:分配前引用了局部变量“ count” - Python: UnboundLocalError: local variable 'count' referenced before assignment UnboundLocalError:赋值python之前引用了局部变量'count' - UnboundLocalError: local variable 'count' referenced before assignment python 错误-UnboundLocalError:分配前已引用本地变量“ VARIABLE_NAME” - Error - UnboundLocalError: local variable 'VARIABLE_NAME' referenced before assignment Fileconveyor错误-UnboundLocalError:分配前已引用局部变量'classname' - Fileconveyor Error - UnboundLocalError: local variable 'classname' referenced before assignment Flask 分页:UnboundLocalError:在赋值错误之前引用了局部变量“res” - Flask Pagination : UnboundLocalError: local variable 'res' referenced before assignment error 我收到错误消息:UnboundLocalError:分配前引用了本地变量'porc' - I got error : UnboundLocalError: local variable 'porc' referenced before assignment Python 错误:UnboundLocalError:赋值前引用了局部变量“score1” - Python error: UnboundLocalError: local variable 'score1' referenced before assignment Tkinter错误UnboundLocalError:赋值之前引用了局部变量“标志” - Tkinter error UnboundLocalError: local variable 'flag' referenced before assignment
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM