在 python 中从全局范围解析变量
resolving variables from global scope in python
我正在尝试更好地理解 python 中的范围界定。我有以下玩具示例:
a = 1
print "in global: " + str(a)
def g():
a += 1
print "in g(): " + str(a)
def f():
a += 1
print "in f(): " + str(a)
g()
f()
我希望这个 运行 并打印出 1
然后 2
然后再次 2
。但是,我得到了 en error:
UnboundLocalError: local variable 'a' referenced before assignment
我原以为 g()
和 f()
都会从全局范围中拉出 a
。不正确?
更新:
感谢您的回答,但不清楚的是:如果我只想读取全局变量 a
并将其分配给我创建的局部变量,也命名为 a
这可能吗?
我这样做的原因是我想弄清楚 g()
是在调用时继承 f()
的范围还是在定义它的全局范围内?
您需要使用 global
关键字。
>>> a = 1
>>> def g():
... global a
... a += 1
... print a
...
>>> g()
2
您在函数 g 和 f 中缺少全局运算符
像这样:
a = 1
def g():
global a
a += 1
print "in g(): " + str(a)
def f():
global a
a += 1
print "in f(): " + str(a)
您可以在 documentation here and from stack overflow here
中找到有关全局变量和局部变量的更多信息
您正试图在函数的外部范围内更改 a
,a
不在当前函数的范围内,这就是您收到此类错误的原因,因为您的函数对此一无所知a
。如果你想在函数中改变 a
你需要使用 `global':
a = 1
print "in global: " + str(a)
def g():
global a
a += 1
print "in g(): " + str(a)
def f():
global a
a += 1
print "in f(): " + str(a)
g()
要打印出全局 a
可以这样使用:
def f():
print a
new_a = a
print new_a
有一个很好的例子global
here
如果您想使用局部变量 a
和全局 a
的值,请使用 globals
:
def g():
a = globals()['a']
a += 1
print "in g(): " + str(a)
当您请求变量值时,Python 遵循 LEGB 规则:本地、封闭、全局、内置。
但是当你分配一个变量时,它是在本地范围内从头开始创建的(假设变量分配是在函数内部),丢弃之前绑定到它的任何值:
a = 5
def f(x):
print a # Prints `5`, because name `a` can be found following LEGB rule in Global scope.
print x # Prints whatever value `x` was having, found following LEGB rule in Local scope.
x = 123 # Forgets previous value of `x`, re-assign it to `123` in the Local scope.
你的未绑定变量问题出现在这里:a += 1
只是 a = a + 1
的语法糖。当您执行 a = a + 1
时,Python 捕获 a
是本地的,因此它会在字节码中生成 LOAD_FAST 命令:
import dis
a = 1
def f():
a += 1
print dis.dis(f)
0 LOAD_FAST 0 (a)
3 LOAD_CONST 1 (1)
6 INPLACE_ADD
7 STORE_FAST 0 (a)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
LOAD_FAST用于获取局部变量。但是当调用 LOAD_FAST 时,您在本地范围内还没有 a
,因此命令失败。
实际上,如果您不分配给 a
,但想从本地范围修改它,您可以通过方法调用来完成。不幸的是,int
没有修改方法,所以我将举一个例子 class:
class Number(object):
def __init__(self, x):
self.x = x
def add_one(self):
self.x += 1
a = Number(1)
def f():
a.add_one()
print a.x
print a.x
f()
print a.x
1
2
2
在这里,您实际上是 a=a+1
,但方式更复杂。这是因为对 a
的调用被解析为全局(并且工作正常)并且您没有在 f()
中进行任何分配。方法 add_one
在现有对象上调用 - 它不关心它在调用者中是全局的还是局部的。
我正在尝试更好地理解 python 中的范围界定。我有以下玩具示例:
a = 1
print "in global: " + str(a)
def g():
a += 1
print "in g(): " + str(a)
def f():
a += 1
print "in f(): " + str(a)
g()
f()
我希望这个 运行 并打印出 1
然后 2
然后再次 2
。但是,我得到了 en error:
UnboundLocalError: local variable 'a' referenced before assignment
我原以为 g()
和 f()
都会从全局范围中拉出 a
。不正确?
更新:
感谢您的回答,但不清楚的是:如果我只想读取全局变量 a
并将其分配给我创建的局部变量,也命名为 a
这可能吗?
我这样做的原因是我想弄清楚 g()
是在调用时继承 f()
的范围还是在定义它的全局范围内?
您需要使用 global
关键字。
>>> a = 1
>>> def g():
... global a
... a += 1
... print a
...
>>> g()
2
您在函数 g 和 f 中缺少全局运算符 像这样:
a = 1
def g():
global a
a += 1
print "in g(): " + str(a)
def f():
global a
a += 1
print "in f(): " + str(a)
您可以在 documentation here and from stack overflow here
中找到有关全局变量和局部变量的更多信息您正试图在函数的外部范围内更改 a
,a
不在当前函数的范围内,这就是您收到此类错误的原因,因为您的函数对此一无所知a
。如果你想在函数中改变 a
你需要使用 `global':
a = 1
print "in global: " + str(a)
def g():
global a
a += 1
print "in g(): " + str(a)
def f():
global a
a += 1
print "in f(): " + str(a)
g()
要打印出全局 a
可以这样使用:
def f():
print a
new_a = a
print new_a
有一个很好的例子global
here
如果您想使用局部变量 a
和全局 a
的值,请使用 globals
:
def g():
a = globals()['a']
a += 1
print "in g(): " + str(a)
当您请求变量值时,Python 遵循 LEGB 规则:本地、封闭、全局、内置。
但是当你分配一个变量时,它是在本地范围内从头开始创建的(假设变量分配是在函数内部),丢弃之前绑定到它的任何值:
a = 5
def f(x):
print a # Prints `5`, because name `a` can be found following LEGB rule in Global scope.
print x # Prints whatever value `x` was having, found following LEGB rule in Local scope.
x = 123 # Forgets previous value of `x`, re-assign it to `123` in the Local scope.
你的未绑定变量问题出现在这里:a += 1
只是 a = a + 1
的语法糖。当您执行 a = a + 1
时,Python 捕获 a
是本地的,因此它会在字节码中生成 LOAD_FAST 命令:
import dis
a = 1
def f():
a += 1
print dis.dis(f)
0 LOAD_FAST 0 (a)
3 LOAD_CONST 1 (1)
6 INPLACE_ADD
7 STORE_FAST 0 (a)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
LOAD_FAST用于获取局部变量。但是当调用 LOAD_FAST 时,您在本地范围内还没有 a
,因此命令失败。
实际上,如果您不分配给 a
,但想从本地范围修改它,您可以通过方法调用来完成。不幸的是,int
没有修改方法,所以我将举一个例子 class:
class Number(object):
def __init__(self, x):
self.x = x
def add_one(self):
self.x += 1
a = Number(1)
def f():
a.add_one()
print a.x
print a.x
f()
print a.x
1
2
2
在这里,您实际上是 a=a+1
,但方式更复杂。这是因为对 a
的调用被解析为全局(并且工作正常)并且您没有在 f()
中进行任何分配。方法 add_one
在现有对象上调用 - 它不关心它在调用者中是全局的还是局部的。