在函数体中使用未定义的变量

时间:2013-05-28 16:25:57

标签: python

有这段代码:

def f():
  x = m 
  m = 2 

def g():
  x = m

f() # UnboundLocalError: local variable 'm' referenced before assignment
g() # NameError: global name 'm' is not defined

在两个函数体中都使用了变量m,它在使用时未定义,但错误消息不同。 Python在使用它们之前是否知道函数中定义了哪些变量(如函数f)?为什么错误消息不同?

6 个答案:

答案 0 :(得分:2)

如果函数中的任何位置都有赋值,那么它在该函数中的任何位置都被视为局部变量。这意味着对于函数f(),即使在尝试访问m后发生m的分配,行[{1}}也只会查找名称{{1}在本地范围内。这就是x = m的错误消息将m称为局部变量的原因。

在函数f()中没有m的分配,因此行g()将使用here描述的顺序查找m

  • 首先搜索的最里面的范围包含本地范围 名称
  • 从最近的封闭范围开始搜索的任何封闭函数的范围包含非本地名称,但也包含非全局名称
  • 倒数第二个范围包含当前模块的全局名称
  • 最外层范围(最后搜索)是包含内置名称的命名空间

x = m的错误消息,“全局名称'm'未定义”,指的是全局范围,因为这是搜索的最后一个位置(内置除外,但它会让人感到困惑)有一条消息,如“在内置命名空间中找不到名称'm'。”。

请注意,您可以使用globalnonlocal语句来更改此行为(m仅存在于Python 3.x中)。

答案 1 :(得分:1)

Python一旦调用它就会检查它。

导入时,直接在解释器中输入时,只关注是否违反了任何语法规则。它并不关心这个级别的本地人或全局。

>>> def foo():
...     print locals()
...     bar = 34
...     print locals()
...     DIP = SET
...
>>>
>>> foo()
{}
{'bar': 34}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in foo
NameError: global name 'SET' is not defined

它从上到下运行,并检查locals()和globals(),如果它看到该变量然后它就可以了,并对它做任何事情。

它甚至适用于定义和子定义......或者您要分配的任何其他内容

>>> def foo():
...     bar()
...     def bar():
...         print("never gonna give you up")
...
>>>
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'bar' referenced before assignment

答案 2 :(得分:0)

是。如果在函数中的任何位置分配变量(不使用global关键字),Python会将函数中对该名称的所有引用视为本地。

答案 3 :(得分:0)

执行函数时,实际上是在函数对象上调用__call()__

解析脚本时,在脚本全局命名空间中创建函数对象。 创建但未执行。

作为解析过程的一部分,计算对象名称空间。因此,解释器实际上可以知道哪个变量存在以及何时存在。

答案 4 :(得分:0)

def f():
  x = m 
  m = 2 

当解析上面的函数时,python认为m是找到m = 2的局部变量,所以当实际调用该函数时x = m会引发错误,因为m是尚未在当地范围内定义。

def g():
  x = m

在这个python中认为m将来自全局范围的某个值,它首先搜索全局命名空间然后搜索内置命令,但是当在任何地方找不到m时,错误是提高。

>>> m = 1
>>> def g():
       x = m
>>> g()         #works fine because `m` is found in global scope

>>> def g():
       x = sum
>>> g()         # sum is found in built-ins

要修改全局变量,请使用global

>>> m = 1
>>> def g():
       global m
       m += 1
...     
>>> g()
>>> m
2

答案 5 :(得分:0)

您需要在函数

中使用global m