我正在努力更好地理解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
。但是,我得到了错误:
UnboundLocalError: local variable 'a' referenced before assignment
我原以为g()
和f()
都会从全局范围中提取a
。不正确的?
更新:
感谢您的回答,但不清楚的是:如果我只想读取全局变量a
并将其分配给我创建的局部变量,那么也可以命名为a
?
我这样做的原因是我试图弄清g()
在调用f()
时是继承let currentLayerTime = myLayer.convertTime(CACurrentMediaTime(), from: nil)
的范围还是在定义它时的全局范围?
答案 0 :(得分:5)
您正在尝试更改功能外部范围内的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)
答案 1 :(得分:4)
您需要使用global
关键字。
>>> a = 1
>>> def g():
... global a
... a += 1
... print a
...
>>> g()
2
答案 2 :(得分:4)
你缺少函数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)
中找到有关全局和局部变量的更多信息
答案 3 :(得分:1)
当你要求变量值时,Python遵循LEGB规则:local,enclosing,global,built-in。
但是当你分配一个变量时,它在本地范围内被创建从头开始(假设变量赋值在函数内部),丢弃以前绑定到它的任何值:
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 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
- 它不关心它在调用者中是全局的还是本地的。