蟒蛇和UnboundLocalError

问题描述:

我有一个小问题局部变量和python(2.7)。蟒蛇和UnboundLocalError

我有一点点代码:

def foo(a): 
    def bar(): 
     print a 
    return bar() 

>>>foo(5) 
5 

那么,它的工作,但如果要修改,如:

def foo(a): 
    def bar(): 
     a -= 1 
    return bar() 
>>>foo(5) 
UnboundLocalError: local variable 'a' referenced before assignment 

所以我一定影响 'a' 到另一个变量。

但我不明白这个方面。 是否因为有一个任务时,python会查找locals()变量并且找不到它?

谢谢。

+1

你为什么要叫'巴()''栏()内'你的第二个例子吗?只要您通过作业行,它必须以“RuntimeError:超过最大递归深度”停止。 – 2012-03-15 13:42:10

+0

http://docs.python.org/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value | http://eli.thegreenplace.net/2011/05/15/understanding-unboundlocalerror-in-python – georg 2012-03-15 13:43:20

+1

在你的第二个例子中,你在bar()中返回bar(),是你想要的还是缩进/复制错误?因为你没有在你的第一个例子 – 2012-03-15 13:44:38

你找到的东西,以前是在Python的问题!简单的答案是,你不能在Python 2.x中做这个(虽然你可以simulate)它,但你可以在3.x中使用nonlocal关键字。

PEP 3104

Before version 2.1, Python's treatment of scopes resembled that of standard C: within a file there were only two levels of scope, global and local. In C, this is a natural consequence of the fact that function definitions cannot be nested. But in Python, though functions are usually defined at the top level, a function definition can be executed anywhere. This gave Python the syntactic appearance of nested scoping without the semantics, and yielded inconsistencies that were surprising to some programmers -- for example, a recursive function that worked at the top level would cease to work when moved inside another function, because the recursive function's own name would no longer be visible in its body's scope. This violates the intuition that a function should behave consistently when placed in different contexts. Here's an example:

def enclosing_function(): 
    def factorial(n): 
     if n < 2: 
      return 1 
     return n * factorial(n - 1) # fails with NameError 
    print factorial(5) 

Python 2.1 moved closer to static nested scoping by making visible the names bound in all enclosing scopes (see PEP 227). This change makes the above code example work as expected. However, because any assignment to a name implicitly declares that name to be local, it is impossible to rebind a name in an outer scope (except when a global declaration forces the name to be global). Thus, the following code, intended to display a number that can be incremented and decremented by clicking buttons, doesn't work as someone familiar with lexical scoping might expect:

def make_scoreboard(frame, score=0): 
    label = Label(frame) 
    label.pack() 
    for i in [-10, -1, 1, 10]: 
     def increment(step=i): 
      score = score + step # fails with UnboundLocalError 
      label['text'] = score 
     button = Button(frame, text='%+d' % i, command=increment) 
     button.pack() 
    return label 

Python syntax doesn't provide a way to indicate that the name score mentioned in increment refers to the variable score bound in make_scoreboard, not a local variable in increment. Users and developers of Python have expressed an interest in removing this limitation so that Python can have the full flexibility of the Algol-style scoping model that is now standard in many programming languages, including JavaScript, Perl, Ruby, Scheme, Smalltalk, C with GNU extensions, and C# 2.0.

+0

好吧,非常感谢! – lundiAuSoleil 2012-03-15 15:22:02

Constantinius给出的理由是正确的。处理这个问题的另一种方式(不使用全局变量)将

def foo(a): 
    def bar(a): 
     a -= 1 
     return a 
    return bar(a) 
>>> print foo(5) 
4