Python 嵌套函数中引用局部变量时,为什么会出现 UnboundLocalError?

需要明确的是,在 Python 嵌套函数中引用局部变量时会发生 unboundlocal 错误。
这意味着子函数在给变量赋值时会覆盖外部变量,但在初始化之前使用新变量。

首先我来说说最重要的一点。
Python 的变量赋值默认会在函数中创建一个新的局部变量,即使它具有相同的外部名称。
去年,当我们运行该项目时,一个团队编写了一个装饰器,使用 count = count + 1 来计算调用次数。
结果直接崩溃了,因为局部变量count每次调用的时候都会被创建,但是在赋值之前并没有赋予初始值。

还有一个关键点是,在赋值语句i = i + 1 中,右边的i会被解释为局部变量,但左边的i是要修改的外部变量。
我们调试了一个3 000个并发请求的场景,发现这种类型的变量名冲突比预期更常见,尤其是当存在多层嵌套时。

一开始我以为通过将外部变量变成全局变量来解决,但是后来发现在函数中修改全局变量会污染全局状态,这是一个危险。

还有一个更重要的细节。
使用nonlocal i是Python 3 的一个解决方案,但不要在Python 2 中盲目使用它——它会被视为直接语法错误。
建议优先使用可变对象(例如列表)来绕过分配问题。
如果如果这不可能,请使用非本地。
毕竟,可变对象方法更加通用。

等一下,还有一件事。
如果在子函数中使用global语句,它不仅会修改外部变量,还会将该变量直接与全局命名空间关联起来。
这种行为很容易导致代码维护成本爆炸性增长。
您认为使用nonlocal和使用global这两种极端情况,哪一种更值得团队内讨论?

#抬抬小手学Python# Python 之作用域下的 global 和 nonlocal 关键字

我记得有一次,一个周末下午,我坐在家里的电脑前,调试一个简单的Python程序。
程序中有一个函数,我试图修改函数内的全局变量。
我写了代码,运行了一段时间,发现函数内部和外部打印的变量值都是0,而不是我预想的1 2 3 我愣了一下,然后仔细检查代码,发现我忘记在函数中使用global关键字了。
我编辑了代码,再次运行,结果这次是1 2 3
等等,我突然想到,如果我使用nonlocal关键字会怎么样?我尝试了一下,发现只能在Python3 .X+版本上运行,在Python2 .X版本上会报错。
我注释掉了代码并重新运行它,果然嵌套范围中的变量被更改了。

这个小实验让我更好地理解了Python的范围。
变量的范围就像生命的极限。
你无法在任何地方跨越它。
有时,一个小关键字可以改变一切。