[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