为什么在Python中给全局变量赋值无效?

95 投票
6 回答
139834 浏览
提问于 2025-04-15 11:56

我在理解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的全局变量作用域规则有什么误解吗?

6 个回答

5

在这个函数里面,a 被当作一个局部变量来处理。你需要在使用它之前,先在函数里面定义一下

global a

即使你在函数外面已经定义过它。

15

理解这个问题的关键在于,当你用 = 给一个变量赋值时,你同时也把它声明为一个局部变量。所以,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 时,你指的是全局变量,而不是局部变量。

188

全局变量是特别的。如果你在一个函数里面给一个变量赋值,比如说 a = value,那么这会在函数内部创建一个新的局部变量,即使外面有一个同名的全局变量。要想访问外面的全局变量,你需要在函数内部加上一个 global 声明

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

想了解更多,可以查看 命名和绑定,里面详细解释了Python的命名和绑定规则。

撰写回答