我有这段代码:
#!/usr/bin/env python
def get_match():
cache=[]
def match(v):
if cache:
return cache
cache=[v]
return cache
return match
m = get_match()
m(1)
如果我运行它,它说:
UnboundLocalError: local variable 'cache' referenced before assignment
但如果我这样做:
#!/usr/bin/env python
def get():
y = 1
def m(v):
return y + v
return m
a=get()
a(1)
它运行。
是不是有什么用列表? 或者我的代码组织是错误的?
问题是,该变量cache
是不是在功能匹配的范围。 这不是一个问题,如果你只想读它作为你的第二个例子,但如果你分配给它,蟒蛇将其解释为一个局部变量。 如果你正在使用Python 3,你可以使用nonlocal
关键字来解决这个问题-为Python 2有没有简单的解决方法,很遗憾。
def f():
v = 0
def x():
return v #works because v is read from the outer scope
def y():
if v == 0: #fails because the variable v is assigned to below
v = 1
#for python3:
def z():
nonlocal v #tell python to search for v in the surrounding scope(s)
if v == 0:
v = 1 #works because you declared the variable as nonlocal
问题是有些全局变量是相同的-你需要使用global
分配给一个全局变量每一次,但不是阅读它。
背后原因是什么的简短解释:Python解释器编译所有功能于类型的特殊对象function
。 在此编译,它会检查所有局部变量的函数创建(垃圾收集等)。 这些变量名保存在函数对象之内。 因为它是完全合法的“影子”的外部范围变量(创建具有相同名称的变量),分配给和未明确声明任何变量global
(或nonlocal
在python3)被认为是一个局部变量。
当执行功能时,解释器来查找每一个变量引用遇到。 如果变量被认为是在编译过程中的地方,就搜索功能f_locals字典。 如果它没有被分配到的是,这引起了你所遇到的异常。 如果职能范围变量没有分配到,因此并不是它的当地人的一部分,它抬头周边范围 - 如果没有找到那里,这就提出了一个类似的异常。
访问一个变量是从分配给它的不同。
你必须与全局变量类似的情况。 您可以访问他们的任何功能,但如果你试图给它没有global
的语句,它会重新声明它在当地的情况。
不幸的是,当地的职能不存在的相当于global
语句,但您可以通过更换绕过重声明
cache=[v]
有:
cache[:] = [v]
由于Python看到cache=[v]
-分配到cache
,它会将其作为局部变量。 因此错误是相当合理的-没有本地变量cache
在其使用之前定义的if
声明。
你可能想将它写为:
def get_match():
cache=[]
def match(v):
if cache:
return cache
cache.append(v)
return cache
return match
m = get_match()
m(1)
强烈推荐阅读: 执行模型-命名和绑定和PEP 227 -静态嵌套的范围
更换
cache=[]
def match(v):
同
def match(v,cache=[])
说明:您的代码声明cache
作为一个变量get_match
,其返回的match(v)
一无所知(由于以下分配)。 然而,你希望cache
成为其中的一部分match
的命名空间。
我知道这样一个“恶意”用户可以重新定义缓存,但是那是他们自己的错误。 如果这是一个问题,不过,另一种方法是:
def match(v):
try:
if cache:
return cache
except NameError:
cache = []
...
(见这里 )