2

我已经开始自学python,并注意到与全局变量和范围有关的一些奇怪的事情。当我运行这个:

x = 2 
y = 3 
z=17 
def add_nums():
    y = 6 
    return z+y

打印 23 的结果...但是,当我将返回扩展为:

x = 2 
y = 3 
z=17 
def add_nums(): 
    y = 6 
    z = z + y 
    return z

我在第 6 行收到以下错误:

Local name referenced but not bound to a value.
A local name was used before it was created. You need to define the     
method or variable before you try to use it.

我很困惑为什么我在这里遇到错误,因为 z 是全局可访问的。

4

4 回答 4

6

Python通过绑定操作确定范围。赋值是一种绑定操作,就像导入一样,使用名称作为目标except .. aswith .. asfor循环,或通过创建函数或类。

当名称绑定在范围内时,它是该范围的本地名称。如果使用了名称但未绑定,则它是非本地的;编译器将在编译时确定范围应该是什么。在您的情况下,除了全局范围之外没有父范围,因此任何未绑定的名称都被视为全局。

由于您的第二个示例绑定到z(您使用z =了一个赋值),因此该名称是函数的本地名称。

如果一个名字被绑定在一个范围内,但你想告诉 Python 它应该是全局的,你需要明确地这样做:

x = 2 
y = 3 
z=17 
def add_nums(): 
    global z
    y = 6 
    z = z + y 
    return z

global z行告诉编译器z应该是全局的,即使您绑定到它

于 2015-05-25T13:48:47.853 回答
6

当变量位于等号左侧时,python 将创建一个局部变量。当变量在等号的右边时,python 会尝试寻找一个局部变量,如果找不到,它将使用一个全局变量。在您的示例中, z 位于等号的右侧和左侧,以避免歧义,python 会引发错误。您需要使用global语法来避免这种情况:

x = 2 
y = 3 
z=17 
def add_nums(): 
    global z
    y = 6 
    z = z + y 
    return z
于 2015-05-25T13:48:55.827 回答
3

让我们分析标记的线。

x = 2
y = 3 
z = 17 
def add_nums(): 
    y = 6 
    z = z + y  <--- THIS LINE
    return z

z ... 创建了一个新的局部变量
= ... 我们将为它赋值
z ... 这个变量存在(新的局部变量)但它还没有值。
+ y ...这部分没有到达。

结果是一条错误消息“UnboundLocalError:分配前引用的局部变量'z'”。

于 2015-05-25T13:54:39.140 回答
1

如果您希望函数体中的名称y和内部在您为它们赋值时z引用您的全局变量,您必须像这样声明它们:

x = 2 
y = 3 
z=17 
def add_nums(): 
    global y 
    global z 
    y = 6
    z = z + y
    return z

y否则,当您对变量和函数内部执行赋值时z,您会创建仅存在于函数局部范围内的不同名称。

正如评论中所指出的,只要您不尝试分配给它,您就可以引用一个全局变量,甚至可以在它是可变的(即,将某些内容附加到列表中)的情况下对其进行修改,而无需明确声明它是全局的。

于 2015-05-25T13:49:08.783 回答