Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在函数中的if语句的条件中使用全局变量时,Python会抛出UnboundLocalError_Python_Python 3.x_Scope - Fatal编程技术网

在函数中的if语句的条件中使用全局变量时,Python会抛出UnboundLocalError

在函数中的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

尽管变量是在全局范围内声明的,但我得到了一个UnboundLocalError。对于该特定语句,似乎假定/强制该变量为局部变量

我不明白为什么if语句条件中的变量会得到不同的处理。有人能解释一下发生了什么事吗

以下代码片段是我试图做的一个简化示例:

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()中找到了以下关于作用域和名称空间的文章,但基于以下内容,我觉得它应该可以正常工作:

虽然范围是静态确定的,但它们是动态使用的。在执行期间的任何时候,至少有三个嵌套作用域的名称空间可以直接访问:

  • 最里面的范围(首先搜索)包含本地名称
  • 从最近的封闭作用域开始搜索的任何封闭函数的作用域都包含非局部名称,但也包含非全局名称
  • 倒数第二个作用域包含当前模块的全局名称
  • 最外层的作用域(最后搜索)是包含内置名称的命名空间
我在Windows 10上的Conda中使用Jupyter 4.4.0和Python 3.6.6以及IPython 6.5.0,但我能够通过控制台IPython和运行Python 3.6.0的空闲3.6.0 GUI重现这种行为

编辑:不知何故,下面的代码段没有受到影响?这似乎与在同一个数据库中更新变量有关。我觉得此刻我一定错过了一些琐碎的事情

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