[Python-Dev] more timely detection of unbound locals

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