[Python-Dev] more timely detection of unbound locals (original) (raw)

Nick Coghlan ncoghlan at gmail.com
Mon May 9 17:17:35 CEST 2011


On Tue, May 10, 2011 at 1:01 AM, Eli Bendersky <eliben at gmail.com> wrote:

I think you are making an unwarranted assumption about what is "more expected". I presume you are thinking that the expected behaviour is that foo() should:

print global x (5) assign 1 to local x print local x (1) If we implemented this change, there would be no more questions about UnboundLocalError, but instead there would be lots of questions like "why is it that globals revert to their old value after I change them in a function?". True, but this is less confusing and follows the rules in a more straightforward way. x = 1 without a 'global x' assigns a local x, this make sense and is similar to what happens in C where an inner declaration temporarily shadows a global one.

However, since flow control constructs in Python don't create new scopes (unlike C/C++), you run into a fundamental problem with cases like the one Isaac posted, or even nastier ones like the following:

def f(): if bar(): fill = 1 else: fiil = 2 print(fill) # Q: What does this do when bool(bar()) is False?

Since we want to make the decision categorically at compile-time, the simplest, least-confusing option is to say "assignment makes a variable name local, referencing it before the first assignment is now an error". I don't know of anyone that particularly likes UnboundLocalError, but it's better than letting errors like the one above pass silently. (It obviously doesn't trap all typo-related errors, but it at least lets you reason sanely about name bindings)

On the reasoning-sanely front, closures likely present a more compelling argument:

def f(): def g(): print(x) # We want this to refer to the closure in f(), thanks x = 1 return g

UnboundLocalError is really about aligning the rules for the current scope with those for references from nested scopes (i.e. x is a local variable of f, whether it is referenced from f's local scope, or any nested scope within f)

Cheers, Nick.

-- Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-Dev mailing list