为什么分配给我的全局变量在Python中不起作用?

时间:2009-05-30 14:09:18

标签: python global-variables scope

我在尝试理解python范围规则时遇到了很大麻烦。

使用以下脚本:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

给出意外(对我而言)输出:

    Before setA
    Value of a is 7
    Inside setA, a is now 42
    After setA
    Value of a is 7

我希望最后一次打印a的值为42,而不是7.我对Python的全局变量范围规则缺少什么?

5 个答案:

答案 0 :(得分:113)

全局变量很特殊。如果尝试在函数内部分配变量a = value,它会在函数内部创建一个新的局部变量,即使存在具有相同名称的全局变量也是如此。要改为访问全局变量,请在函数内添加global statement

a = 7
def setA(value):
    global a   # declare a to be a global
    a = value  # this sets the global value of a

另请参阅Naming and binding以获取有关Python命名和绑定规则的详细说明。

答案 1 :(得分:12)

理解这一点的技巧是,当你使用=分配给变量时,你也将它声明为局部变量。因此,setA(value)不是改变全局变量a的值,而是实际上将一个局部变量(恰好称为a)设置为传入的值。

如果您尝试在setA(value)的开头打印a的值,则会变得更加明显:

def setA(value):
    print "Before assignment, a is %d" % (a)
    a = value
    print "Inside setA, a is now %d" % (a)

如果您尝试运行此Python,将会给您一个有用的错误:

Traceback (most recent call last):
  File "scopeTest.py", line 14, in 
    setA(42)
  File "scopeTest.py", line 7, in setA
    print "Before assignment, a is %d" % (a)
UnboundLocalError: local variable 'a' referenced before assignment

这告诉我们Python决定setA(value)函数有一个名为a的局部变量,这是你在函数中赋值时改变的。如果你没有在函数中指定a(就像printA())那么Python使用全局变量A.

要将变量标记为全局变量,您需要在Python中使用global关键字,在要使用全局变量的范围内。在这种情况下,它在setA(value)函数内。因此脚本变为:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    global a
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

这一行添加告诉Python当你在setA(value)函数中使用变量a时,你正在谈论全局变量,而不是局部变量。

答案 2 :(得分:1)

Python没有像其他语言那样的变量概念。您有“某处”的对象,并且您具有对这些对象的引用。 =用于将这些对象分配给当前命名空间中的引用。

您在setA函数的名称空间中创建名称a,该名称引用值所引用的对象。

答案 3 :(得分:1)

在函数内部, a 被视为局部变量,需要定义

  

全球a

在函数内部

答案 4 :(得分:0)

函数的执行引入了一个新的符号表,用于该函数的局部变量。更准确地说,函数中的所有变量分配都将值存储在本地符号表中。变量引用首先在本地符号表中查找,然后在封闭函数的本地符号表中查找,然后在全局符号表中查找,最后在内置名称表中查找。因此,尽管可以引用全局变量,但不能在函数内直接为其赋值(除非在全局语句中命名)。