繁体   English   中英

UnboundLocalError:在python闭包中赋值之前引用的局部变量

[英]UnboundLocalError: local variable referenced before assignment in python closure

我用Python实现了两个简单的闭包。 在我看来,它们看起来一样,但是其中一种有效而另一种无效。

工作的是:

def makeInc(x, y):
    def inc():
        return y + x
    return inc

inc5 = makeInc(5, 10)
inc10 = makeInc(10, 5)

inc5 () # returns 15
inc10() # returns 15

但是第二个不起作用:

import os
def linker(dest, filename):
    print filename
    def link(): 
        if os.path.isfile(filename): # line 17
            filename = os.path.join(os.getcwd(), filename)
            dest = os.path.join(dest, filename)
            y = rawinput('[y]/n: ln -sf %s %s' % (dest, filename))
            if y == 'n':
                return 1
            else:
                return os.system('ln -sf %s %s' %(dest, filename))
        else:
            return -1
    return link

l = linker('~', '.vimrc')
l()  # line 30

执行l()时,它会在link()的第一行发生故障:

Traceback (most recent call last):
  File "test.py", line 30, in <module>
    l()
  File "test.py", line 17, in link
    if os.path.isfile(filename):
UnboundLocalError: local variable 'filename' referenced before assignment

它们对我来说似乎完全相同,所以我不明白为什么第二个不起作用。 任何的想法?

您已经用filename = os.path.join(os.getcwd(), filename)覆盖了变量,如果将filename =更改为不同于filename ,则不会local variable 'filename' referenced before assignment错误local variable 'filename' referenced before assignment得到local variable 'filename' referenced before assignmentlocal variable 'filename' referenced before assignment

一旦您设置filename =您不再参照参数filename是在你指的是本地通过filename中,你尝试在使用,如果你收到定义的内部函数的范围。

如果将两行和其他变量更改为类似的内容,则dest将会遇到相同的问题:

filename_ = os.path.join(os.getcwd(), filename)
dest_ = os.path.join(dest, filename)

您会看到代码可以正常运行,因为filename现在指向的是参数,而不是内部函数中定义的局部变量。

如果您尝试在第一个函数中重新分配x并在定义x之前尝试访问x ,将会看到完全相同的行为:

def makeInc(x, y):
    def inc():
        print  y + x # will cause referenced before assignment error
        x = 5 # now x is local to the inner func, the x from the outer function is overridden
        return y + x
    return inc

如果打印__closure__属性,您将看到发生的情况:

def makeInc(x, y):
    def inc():
        return y + x
    return inc

inc5 = makeInc(5, 10)
inc10 = makeInc(10, 5)
print(inc5.__closure__)
(<cell at 0x7f180df67e50: int object at 0xef00f8>, <cell at 0x7f180df67fa0: int object at 0xef0080>)

现在重新分配x:

def makeInc(x, y):
    def inc():
        print  y + x
        x= 5
        return y + x
    return inc

inc5 = makeInc(5, 10)
inc10 = makeInc(10, 5)
print(inc5.__closure__)
(<cell at 0x7fea11889fd8: int object at 0x291e080>,)

重新分配内部函数后,将不再引用x

因此,基本上,两个原始函数之间的根本区别在于,在一个函数中,您是在局部范围内重新分配变量,而在另一个函数中,则不是。 从上面的代码可以看到,如果在第一个函数中执行类似的操作,则结果将完全相同。

关于示波器LEGB等, 这里有一个很好的说明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM