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

Nick Coghlan ncoghlan at gmail.com
Sun May 6 22:51:03 EDT 2018

On 7 May 2018 at 11:32, Tim Peters <tim.peters at gmail.com> wrote:

> I have a long history of arguing that magically created lexically
> nested anonymous functions try too hard to behave exactly like
> explicitly typed lexically nested functions, but that's the trendy
> thing to do so I always lose ;-)

You have the reasoning there backwards: implicitly nested scopes behave
like explicitly nested scopes because that was the *easy* way for me to
implement them in Python 3.0 (since I got to re-use all the pre-existing
compile time and runtime machinery that was built to handle explicit
lexical scopes). Everything else I tried (including any suggestions made by
others on the py3k mailing list when I discussed the problems I was
encountering) ran into weird corner cases at either compile time or run
time, so I eventually gave up and proposed that the implicit scope using to
hide the iteration variable name binding be a full nested closure, and we'd
just live with the consequences of that.

The sublocal scoping proposal in the earlier drafts of PEP 572 was our
first serious attempt at defining a different way of doing things that
would allow names to be hidden from surrounding code while still being
visible in nested suites, and it broke people's brains to the point where
Guido explicitly asked Chris to take it out of the PEP :)

However, something I *have* been wondering is whether or not it might make
sense to allow inline scoping declarations in comprehension name bindings.
Then your example could be written:

    def ...:
        p = None
        while any(n % p for nonlocal p in small_primes):
            # p was declared as nonlocal in the nested scope, so our p
points to the last bound value

Needing to switch from "nonlocal p" to "global p" at module level would
likely be slightly annoying, but also a reminder that the bound name is now
visible as a module attribute.

If any other form of comprehension level name binding does eventually get
accepted, then inline scope declarations could similarly be used to hoist
values out into the surrounding scope:

        rem = None
        while any((nonlocal rem := n % p) for nonlocal p in small_primes):
            # p and rem were declared as nonlocal in the nested scope, so
our rem and p point to the last bound value


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180507/1a8c9e19/attachment.html>

More information about the Python-ideas mailing list