2012-03-15 2 views
2

지역 변수 및 Python (2.7)에 약간의 문제가 있습니다. 그것은 작동하고,python 및 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 

그래서 I '는'또 다른 변수에 영향을해야합니다.

하지만이 컴필레이션을 이해하지 못합니다. 할당이있을 때 python은 locals() 변수를보고 찾지 못하기 때문에 그렇습니까?

감사합니다.

+1

가 왜'줄을 호출()''바()의 내부에'두 번째 예? 할당 된 줄을지나 자마자'RuntimeError : maximum recursion depth exceeded '로 멈춰야합니다. –

+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

+1

두 번째 예제에서는 bar()를 bar()로 반환합니다. 원하는 것 또는 들여 쓰기/복사 오류입니다. ? 첫 번째 예가 없으므로 –

답변

8

입니다. 이전에 Python에서 문제였던 것을 발견했습니다! 간단히 대답하면 파이썬 2.x에서는 이것을 할 수 없지만 (simulate 일 수 있음) nonlocal 키워드를 사용하여 3.x에서 할 수 있습니다.

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

2

Constantinius에서 제공 한 이유가 정확합니다. 전역 변수를 사용하지 않고이를 처리하는 또 다른 방법은

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