当您询问变量值时,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
在现有对象上调用 - 它不关心调用者是全局还是本地。
在你的第二段代码中,你不需要'global' – gil
@gill更正,谢谢 – tinySandy