[Python-Dev] Looking for examples: proof that a list comp is a function

Tim Peters tim.peters at gmail.com
Mon May 14 04:05:27 EDT 2018


[Chris Angelico <rosuav at gmail.com]
> ...
> With current semantics, you can easily prove that a list comp is
> implemented with a function by looking at how it interacts with other
> scopes (mainly class scope), but Tim's proposal may change that.

Absolutely not.  I haven't considered for a nanosecond that anything
_essential_ would change in the current implementation.  In effect, my
proposal to

    bind assignment statement targets
        that appear in a listcomp or genexp
    in the blocks that immediately contain their synthetic functions

"merely" sprinkles in some `nonlocal` and/or `global` declarations to
change the targets' scopes.  Indeed, it _relies_ on that they're
implemented as (potentially nested) synthetic functions today.  And if
you haven't read my proposed changes to the reference manual, they
explicitly state that they're talking about the synthetic functions
created to implement genexps and listcomps.


> So I'm looking for examples that prove that a list comp is executed
> inside an implicit function. Ideally, examples that are supported by
> language guarantees, but something that's "CPython has done it this
> way since 3.0" is important too.

I don't believe you'll find that - but, of course, may be wrong about that.

> I'm aware of just two: the name lookup interaction that may be
> changing, and the fact that there's an extra line in a traceback. And
> the latter, as far as I know, is not guaranteed (and I doubt anyone
> would care if it changed). Are there any other provable points?

Nick pointed me to these future docs that _will_ pretty much imply it:

https://docs.python.org/dev/reference/expressions.html#displays-for-lists-sets-and-dictionaries

In part:

"""
However, aside from the iterable expression in the leftmost for
clause, the comprehension is executed in a separate implicitly nested
scope. This ensures that names assigned to in the target list don’t
“leak” into the enclosing scope.

The iterable expression in the leftmost for clause is evaluated
directly in the enclosing scope and then passed as an argument to the
implictly nested scope.
"""

I say "pretty much" because, for whatever reason(s), it seems to be
trying hard _not_ to use the word "function".  But I can't guess what
"then passed as an argument to the implicitly nested scope" could
possibly mean otherwise (it doesn't make literal sense to "pass an
argument" to "a scope").


More information about the Python-Dev mailing list