在函数中的if语句的条件中使用全局变量时,Python会抛出UnboundLocalError
尽管变量是在全局范围内声明的,但我得到了一个UnboundLocalError。对于该特定语句,似乎假定/强制该变量为局部变量 我不明白为什么if语句条件中的变量会得到不同的处理。有人能解释一下发生了什么事吗 以下代码片段是我试图做的一个简化示例:在函数中的if语句的条件中使用全局变量时,Python会抛出UnboundLocalError,python,python-3.x,scope,Python,Python 3.x,Scope,尽管变量是在全局范围内声明的,但我得到了一个UnboundLocalError。对于该特定语句,似乎假定/强制该变量为局部变量 我不明白为什么if语句条件中的变量会得到不同的处理。有人能解释一下发生了什么事吗 以下代码片段是我试图做的一个简化示例: In [1]: global mock ... mock = False ... ... ... def foo(): ... if not mock: ... # do stuff
In [1]: global mock
... mock = False
...
...
... def foo():
... if not mock:
... # do stuff
... mock = True
...
... # do other stuff
...
...
... foo()
尽管函数声明正上方声明了全局bool,但这会引发UnboundLocalError
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-31-540737067cb1> in <module>()
7
8
----> 9 foo()
<ipython-input-31-540737067cb1> in foo()
3
4 def foo():
----> 5 if not mock:
6 mock = True
7
UnboundLocalError: local variable 'mock' referenced before assignment
类似地,if语句体中包含变量的此代码段也按预期运行:
In [2]: mock = False
...
...
... def bar():
... return mock
...
...
... bar()
Out[2]: False
In [3]: mock = False
...
...
... def foobar():
... if True:
... return mock
...
... return True
...
...
... foobar()
Out[3]: False
我在docs()中找到了以下关于作用域和名称空间的文章,但基于以下内容,我觉得它应该可以正常工作:
虽然范围是静态确定的,但它们是动态使用的。在执行期间的任何时候,至少有三个嵌套作用域的名称空间可以直接访问:
- 最里面的范围(首先搜索)包含本地名称
- 从最近的封闭作用域开始搜索的任何封闭函数的作用域都包含非局部名称,但也包含非全局名称
- 倒数第二个作用域包含当前模块的全局名称
- 最外层的作用域(最后搜索)是包含内置名称的命名空间
In [4]: global mock # also works without this line
... mock = False
...
...
... def foo1():
... if not mock:
... return mock
...
... return True
...
...
... foo1()
Out[4]: False
变量是函数作用域。因为函数中有一个名为
mock
的赋值,所以对mock
的所有引用都尝试为“本地”(它们实际上被编译为不同的操作码!)
您可以通过在函数中使用global mock
来更改此设置(因此赋值和引用被强制为global)
请注意,在您的第一个示例中,您在模块范围内编写了global mock
——这不起任何作用:)
直接查看拆卸可能更有意义:
>>> import dis
>>> def f():
... if not mock:
... mock = True
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (mock)
3 POP_JUMP_IF_TRUE 15
3 6 LOAD_GLOBAL 0 (True)
9 STORE_FAST 0 (mock)
12 JUMP_FORWARD 0 (to 15)
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
>>> def g():
... global mock
... if not mock:
... mock = True
...
>>> dis.dis(g)
3 0 LOAD_GLOBAL 0 (mock)
3 POP_JUMP_IF_TRUE 15
4 6 LOAD_GLOBAL 1 (True)
9 STORE_GLOBAL 0 (mock)
12 JUMP_FORWARD 0 (to 15)
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
如果您发现此答案或解决方案有用,请单击绿色复选标记。
>>> import dis
>>> def f():
... if not mock:
... mock = True
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (mock)
3 POP_JUMP_IF_TRUE 15
3 6 LOAD_GLOBAL 0 (True)
9 STORE_FAST 0 (mock)
12 JUMP_FORWARD 0 (to 15)
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
>>> def g():
... global mock
... if not mock:
... mock = True
...
>>> dis.dis(g)
3 0 LOAD_GLOBAL 0 (mock)
3 POP_JUMP_IF_TRUE 15
4 6 LOAD_GLOBAL 1 (True)
9 STORE_GLOBAL 0 (mock)
12 JUMP_FORWARD 0 (to 15)
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE