我会尝试在 Oscar 和 Martijn 已经给出的好答案中添加一些内容。
当你在 python 中读取一个函数时,任何函数,你都必须阅读它两次。总是。
在第一遍中,您应该这样做:对于每个global
和nonlocal
声明语句,将它们(概念上)移动到函数的开头。
对于以下形式的每个陈述
* x = expr (or "x += expr", "x *= expr", etc.)
* for x in expr:
* with expr as x:
* def x(...):
* class x:
* import x (or "import foo as x")
* from some_module import x (or "from some_module import foo as x")
取名字 x,看看:如果它是在global
ornonlocal
语句中声明的,就把它留在那里。否则,将其添加到local
声明中,就在global
and之后nonlocal
。(python中没有local
关键字。这都是概念上的)。函数参数始终是本地的。这些语句中的名称应该是互斥的,就像它们引用的范围一样。
这是第一关。现在您可以坐下来阅读代码了。任何时候你看到一个变量名,你都会在这三个语句中查找它 - global
,nonlocal
以及我们想象中的local
。如果名字在那里 - 你知道它属于哪里。否则,在任何封闭函数上以相同的方式查找它,然后在全局命名空间中查找。如果它不存在,它应该是内置的 - 或错误。
为 完成此操作后update()
,您将获得:
def update():
local testing # not real python code
print "UPDATED"
testing = 2
嗯,这不是你的意思,对吧?
另一个例子,之前:
x=3
def print5():
for i in range(5):
print(x)
x += 1
后:
x=3
def print5():
local i, x
for i in range(5):
print(x) # oops. x is local but was not assigned!
x += 1
请注意,我描述的算法并不完整。我省略了例外,except
它只隐藏子句的名称;eval
和exec
; 和from some_module import *
。
有关完整信息,请参阅文档:http ://docs.python.org/2/reference/executionmodel.html#naming-and-binding