[Python-Dev] global variable modification in functions [Re: elimination of scope bleeding of iteration variables]
Ben Wing
ben at 666.com
Mon May 1 05:47:07 CEST 2006
Nick Coghlan wrote:
> Ben Wing wrote:
>
>> apologies if this has been brought up on python-dev already.
>>
>> a suggestion i have, perhaps for python 3.0 since it may break some
>> code (but imo it could go into 2.6 or 2.7 because the likely breakage
>> would be very small, see below), is the elimination of the misfeature
>> whereby the iteration variable used in for-loops, list
>> comprehensions, etc. bleeds out into the surrounding scope.
>>
>> [i'm aware that there is a similar proposal for python 3.0 for list
>> comprehensions specifically, but that's not enough.]
>
>
> List comprehensions will be fixed in Py3k. However, the scoping of for
> loop variables won't change, as the current behaviour is essential for
> search loops that use a break statement to terminate the loop when the
> item is found. Accordingly, there is plenty of code in the wild that
> *would* break if the for loop variables were constrained to the for
> loop, even if your own code wouldn't have such a problem.
>
> Outside pure scripts, significant control flow logic (like for loops)
> should be avoided at module level. You are typically much better off
> moving the logic inside a _main() function and invoking it at the end
> of the module. This avoids the 'accidental global' problem for all of
> the script-only variables, not only the ones that happen to be used as
> for loop variables.
i did in fact end up doing that. however, in the process i ran into
another python annoyance i've tripped over repeatedly: you can't assign
to a global variable without explicitly declaring it as `global'.
instead, you "magically" get a shadowing local variable. this behavior
is extremely hostile to newcomers: e.g.
foo = 1
def set_foo():
foo = 2
print foo
--> 1
the worst part is, not a single warning from Python about this. in a
large program, such a bug can be very tricky to track down.
now i can see how an argument against changing this behavior might hinge
upon global names like `hash' and `list'; you certainly wouldn't want an
intended local variable called `hash' or `list' to trounce upon these.
but this argument confuses lexical and dynamic scope: global variables
declared inside a module are (or can be viewed as) globally lexically
scoped in the module, whereas `hash' and `list' are dynamically scoped.
so i'd suggest:
[1] ideally, change this behavior, either for 2.6 or 3.0. maybe have a
`local' keyword if you really want a new scope.
[2] until this change, python should always print a warning in this
situation.
[3] the current 'UnboundLocal' exception should probably be more
helpful, e.g. suggesting that you might need to use a `global foo'
declaration.
ben
More information about the Python-Dev
mailing list