为什么在Python中无法分配全局变量?


72

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

给我意外的输出:

    在setA之前
    a的值为7
    在setA内,a现在为42
    setA之后
    a的值为7

我期望a值的最后打印结果是42,而不是7。在Python中,对全局变量进行作用域定义的范围规则使我遗漏了什么?

Answers:


141

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


13

理解这一点的技巧是,当您使用=分配给变量时,还需要将其声明为局部变量。因此,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行,在 
    setA(42)
  setA中的文件“ scopeTest.py”,第7行
    打印“分配前,a为%d”%(a)
UnboundLocalError:赋值之前引用了局部变量“ a”

这告诉我们Python已确定setA(value)函数具有一个称为a的局部变量,这是在函数中为其分配时所更改的。如果您未在函数中分配给a(与printA()一样),则Python使用全局变量A。

要将变量标记为全局变量,您需要在Python中要使用global variable的范围内使用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

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

全球

在函数内部


1

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

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


0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.