蟒闭合与内部函数内部分配外可变(python closure with assigning oute

2019-06-27 07:46发布

我有这段代码:

#!/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)

它运行。

是不是有什么用列表? 或者我的代码组织是错误的?

Answer 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字典。 如果它没有被分配到的是,这引起了你所遇到的异常。 如果职能范围变量没有分配到,因此并不是它的当地人的一部分,它抬头周边范围 - 如果没有找到那里,这就提出了一个类似的异常。



Answer 2:

访问一个变量是从分配给它的不同。

你必须与全局变量类似的情况。 您可以访问他们的任何功能,但如果你试图给它没有global的语句,它会重新声明它在当地的情况。

不幸的是,当地的职能不存在的相当于global语句,但您可以通过更换绕过重声明

cache=[v]

有:

cache[:] = [v]


Answer 3:

由于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 -静态嵌套的范围



Answer 4:

更换

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 = []
     ...

(见这里 )



文章来源: python closure with assigning outer variable inside inner function