unintuitive for-loop behavior

Brendan Abel 007brendan at gmail.com
Thu Sep 29 15:55:14 EDT 2016


Yes, loops don't have their own scope.  Indeed, very few flow elements in
python -- if, with, try/except -- create a new scope.  In that sense, it's
fairly consistent, but can be unexpected for people that have used
languages with many nested scopes.

The lambda behavior is a common gotcha - there are hundreds of questions on
StackOverflow that are caused by that misunderstanding

http://stackoverflow.com/questions/7368522/weird-behavior-lambda-inside-list-comprehension

The most common solution is to just provide the variable as a default
argument to the lambda function, which will bind it how you'd expect

    [lambda base, exponent=exponent: (base ** exponent) for exponent in
range(9)]

On Thu, Sep 29, 2016 at 12:29 PM, <namenobodywants at gmail.com> wrote:

> hello pythonistas
>
> 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?
>
> and it gets even worse; consider the following means of raising an
> exception:
>
> #)-------------------------------------- begin code
>
> def powerfunction(exponent):
>     return lambda base: (base ** exponent)
>
> p1 = [powerfunction(exponent)         for exponent in range(9)]
> p2 = [lambda base: (base ** exponent) for exponent in range(9)]
>
> assert p1[3](4) == p2[3](4)
>
> #)---------------------------------------- end code
>
> apparently the problem is that "exponent" gets evaluated when the relevant
> lambda function is run, not when it's defined, but no binding for
> "exponent" gets put into the enclosing namespace: it seems that python
> remembers this ghostly "exponent" for me on the theory that i don't WANT
> "p1" and "p2" to be the same; can anyone help to reconcile me to this
> semantics?
>
> thanks if you can help
> stm
>
>
>
>
>
>
>
>
>
> --
> https://mail.python.org/mailman/listinfo/python-list
>



More information about the Python-list mailing list