Python全局变量/作用域混淆



我开始自学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是全局的可访问的。

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

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

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应该是一个全局变量,,即使你绑定到它

让我们分析一下标记的行。

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

z……创建一个新的局部变量
=……我们要给它赋一个值
z……这个变量已经存在(新的本地变量),但是还没有值。
+ y…未到达此部分

结果是一个错误消息"UnboundLocalError: local variable 'z' reference before assign "

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

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

否则,当你在函数内对变量yz赋值时,你会创建不同的名字,这些名字只存在于函数的局部作用域中。

正如在评论中指出的,你可以引用一个全局变量,甚至修改它,如果它是可变的(即追加一些东西到一个列表),而不显式地声明它是全局的,只要你不试图分配给它。

最新更新