[Python-ideas] A comprehension scope issue in PEP 572

Steven D'Aprano steve at pearwood.info
Tue May 8 14:19:32 EDT 2018

On Tue, May 08, 2018 at 01:28:59PM -0400, Juancarlo Añez wrote:
> So the way I envision it is that *in the absence of a nonlocal or global
> > declaration in the containing scope*, := inside a comprehension or genexpr
> > causes the compiler to assign to a local in the containing scope, which is
> > elevated to a cell (if it isn't already). If there is an explicit nonlocal
> > or global declaration in the containing scope, that is honored.
> >
> This seems to be getting awfully complicated. Proof? Try to write the docs
> for the proposed semantics.

Okay, I'll bite. I don't know why you think its complicated: it is 
precisely the same as ordinary ``=`` assignment scoping rules. It is 
comprehensions that are the special case.

* * * 

The binding expression ``<name> := <value>`` evaluates the right hand 
side <value>, binds it to <name>, and then returns that value.

Unless explicitly declared nonlocal or global (in which case that 
declaration is honoured), <name> will belong to the current scope, the 
same as other assignments such ``name = value``, with one difference.

Inside comprehensions and generator expressions, variables created with 
``for name in ...`` exist in a separate scope distinct from the usual 
local/nonlocal/global/builtin scopes, and are inaccessible from outside 
the comprehension. (They do not "leak".) That is not the case for those 
created with ``:=``, which belong to the scope containing the 
comprehension. To give an example:

    a = 0
    x = [b := 10*a for a in (1, 2, 3)]
    assert x == [10, 20, 30]
    assert a = 0
    assert b = 30

> I don't understand why we went so astray from the original requirements,
> which could all be met by having `if` and `while` accept `as` to bind an
> expression to a variable that would be local to the structured statement.

That is not the original motivation for binding expressions. The 
original requirements were specifically for comprehensions.


This is hardly the only time that something similar has been raised.


More information about the Python-ideas mailing list