78

我在尝试理解 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()

给出了意想不到的(对我而言)输出:

    设置A之前
    a 的值为 7
    在 setA 中,a 现在是 42
    设置A之后
    a 的值为 7

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

4

5 回答 5

159

全局变量是特殊的。如果您尝试分配给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 命名和绑定规则的详细说明,另请参阅命名和绑定。

于 2009-05-30T14:12:14.883 回答
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 会给你一个有用的错误:

回溯(最近一次通话最后):
  文件“scopeTest.py”,第 14 行,在
    设置A(42)
  文件“scopeTest.py”,第 7 行,在 setA 中
    print "赋值前,a 为 %d" % (a)
UnboundLocalError:分配前引用的局部变量“a”

这告诉我们 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 时,您正在谈论的是全局变量,而不是局部变量。

于 2009-05-30T14:17:00.927 回答
3

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

全球

在方法内部使用它之前,即使您已经在方法外部定义了它。

于 2010-01-16T10:03:30.887 回答
2

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

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

于 2009-05-30T22:26:57.287 回答
0

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

于 2018-08-07T11:42:27.523 回答