简体   繁体   English

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

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

I implemented two simple closures in Python. 我用Python实现了两个简单的闭包。 To me, they looks the same, but one works and the other doesn't. 在我看来,它们看起来一样,但是其中一种有效而另一种无效。

The working one is: 工作的是:

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

But the second one doesn't work: 但是第二个不起作用:

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

It faults at the first line of link() when executing l() : 执行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

They seem identical to me so I don't understand why the second one doesn't work. 它们对我来说似乎完全相同,所以我不明白为什么第二个不起作用。 Any idea? 任何的想法?

You have overwritten the variable with filename = os.path.join(os.getcwd(), filename) , if you change the filename = to something other than filename you won't get a local variable 'filename' referenced before assignment error. 您已经用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

Once you set filename = you are no longer referring to the parameter filename that is passed in you are referring to the local filename in the scope of the inner function which you try to use in the if before you have it defined. 一旦您设置filename =您不再参照参数filename是在你指的是本地通过filename中,你尝试在使用,如果你收到定义的内部函数的范围。

You will have the same problem with dest, if you change the two lines and the other variables to something like: 如果将两行和其他变量更改为类似的内容,则dest将会遇到相同的问题:

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

You will see the code runs fine as filename now refers to the parameter not to a local variable defined in your inner function. 您会看到代码可以正常运行,因为filename现在指向的是参数,而不是内部函数中定义的局部变量。

You will see the exact same behaviour if you try to reassign x in your first function and try to access x before you have defined it: 如果您尝试在第一个函数中重新分配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

If you print the __closure__ attribute you will see what happens: 如果打印__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>)

Now reassigning x: 现在重新分配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>,)

After reassigning in the inner function, there is no longer a reference to x . 重新分配内部函数后,将不再引用x

So basically the fundamental difference between your two original functions is that in one you are reassigning the variable in the local scope and in the other you are not. 因此,基本上,两个原始函数之间的根本区别在于,在一个函数中,您是在局部范围内重新分配变量,而在另一个函数中,则不是。 As you can see from the code above if you do something similar in the first function the outcome is exactly the same. 从上面的代码可以看到,如果在第一个函数中执行类似的操作,则结果将完全相同。

There is a nice tut here on scopes LEGB etc.. 关于示波器LEGB等, 这里有一个很好的说明。

暂无
暂无

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

相关问题 UnBoundLocalError:赋值之前引用的局部变量(Python) - UnBoundLocalError: local variable referenced before assignment (Python) python - UnboundLocalError:分配前引用的局部变量 - python - UnboundLocalError: local variable referenced before assignment Python-UnboundLocalError:分配前引用的局部变量 - Python - UnboundLocalError: local variable referenced before assignment` Python UnboundLocalError:分配前引用了局部变量 - Python UnboundLocalError: local variable referenced before assignment Python | 如果变量:| UnboundLocalError:赋值前引用的局部变量&#39;variable&#39; - Python | if variable: | UnboundLocalError: local variable 'variable' referenced before assignment Python(3.3):UnboundLocalError:分配前已引用局部变量 - Python (3.3): UnboundLocalError: local variable referenced before assignment Python 分裂问题 UnboundLocalError:分配前引用了局部变量“e” - Python Splinter issue UnboundLocalError: local variable 'e' referenced before assignment UnboundLocalError:分配前引用的局部变量“转” - python - UnboundLocalError: local variable 'turn' referenced before assignment - python 如何修复 UnboundLocalError:在 Python 中分配之前引用的局部变量“df” - How to fix UnboundLocalError: local variable 'df' referenced before assignment in Python UnboundLocalError:在 Python3 中赋值之前引用了局部变量“sumOfOdd” - UnboundLocalError: local variable 'sumOfOdd' referenced before assignment in Python3
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM