unintuitive for-loop behavior

Chris Angelico rosuav at gmail.com
Thu Sep 29 19:19:09 EDT 2016


On Fri, Sep 30, 2016 at 5:29 AM,  <namenobodywants at gmail.com> wrote:
> i've had a nodding acquaintance with python for some time, and all along i assumed that for-loops got a namespace of their own; now i'm reading up on the language and i find out that's not the case: the loop variable gets put into the enclosing namespace, overwriting any former value that was already there; of course i realize there are situations where one is interested in the value that a loop variable has after the loop has been exited, but this behavior seems grossly unintuitive to me: has there ever been any discussion of giving for-loops the option of running in namespaces of their own?
>

No, there hasn't. In Python, there are no sub-function scopes - even
the couple of cases that look like subscopes (list comps and genexps)
are actually implemented as nested functions (fairly obvious in the
case of a genexp, more subtle with the list comp). C-like languages
can have infinitely nested scopes because they have variable
declarations:

int some_func() {
    int foo;
    for (...) {
        if (whatever) {
            foo = 1234;
        } else {
            foo = 2345;
        }
        use(foo);
    }
}

The placement of 'int foo;' determines the scope of that name. Python
doesn't have that, so your options are:

1) The first assignment to a name determines its scope. That would
mean that the two assignments are in different scopes, and use(foo) is
not included. To solve this, you'd need a dummy assignment further up
(eg where "int foo" is) - not impossible but probably annoying.

2) Have a single and simple scoping rule, like "anything that's
assigned to is function-local".

Python chose the second option. Anything you assign to is local to the
function, but nothing narrower. There is no way [1] to have a local
name in a function AND use a global with the same name, even in
different parts of the function. Since a 'for' loop is assignment
("for X in Y" assigns to X), that name has to be function-scoped. You
could, in theory, have the name be unbound after the loop, but it's
usually not beneficial to do so, and can be detrimental.

ChrisA

[1] Well, you can use globals(), but that's not quite the same thing
as variable scope.



More information about the Python-list mailing list