[Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part) (original) (raw)

Tim Peters tim.peters at gmail.com
Sun Jun 24 15:03:07 EDT 2018


[Guido]

A quick follow-up: PEP 572 currently has two ideas: (a) introduce := for inline assignment, (b) when := is used in a comprehension, set the scope for the target as if the assignment occurred outside any comprehensions. It seems we have more support for (a) than for (b) -- at least Nick and Greg seem to be +0 or better for (a) but -1 for (b). IIRC (b) originated with Tim. But his essay on the topic, included as Appendix A ( https://www.python.org/dev/peps/pep-0572/#appendix-a-tim-peters-s-findings) does not even mention comprehensions.

I was writing up my observations about simple changes to existing code. Since there's nothing sanely akin to binding non-for-targets possible in comprehensions now, comprehensions were out of scope for that effort (which was limited to staring at existing code already doing bindings).

:> However, he did post his motivation for (b) on python-ideas, IIRC a bit

before PyCon; and the main text of the PEP gives a strong motivation (https://www.python.org/dev/peps/pep-0572/#scope-of-the-target). Nevertheless, maybe we should compromise and drop (b)?

Two things to say about that. First, the original example I gave would be approximately as well addressed by allowing to declare intended scopes in magically synthesized functions; like (say)

p = None # to establish the intended scope of p while any( # split across lines just for readability n % p == 0 for p in small_primes): n //= p

It didn't really require an inline assignment, just a way to override the unwanted (in this case) "all for targets are local to the invisible function" rigid consequence of the implementation du jour.

Second, if it's dropped, then the PEP needs more words to define what happens in cases like the following, because different textual parts of a comprehension execute in different scopes, and that can become visible when bindings can be embedded:

def f(): y = -1 ys = [y for _ in range(y := 5)] print(y, ys)

Here range(y := 5) is executed in f's scope. Presumably the y in y for also refers to f's scope, despite that y textually appears to be assigned to in the body of the listcomp, and so would - for that reason - expected to be local to the synthesized function, and so raise UnboundLocalError when referenced. It's incoherent without detailed knowledge of the implementation.

def g(): y = -1 ys = [y for y in range(y := 5)] print(y, ys)

And here the y in y for y is local to the synthesized function, and presumably has nothing to do with the y in the range() call. That's incoherent in its own way.

Under the current PEP, all instances of y in f refer to the f-local y, and the listcomp in g is a compile-time error. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-dev/attachments/20180624/f9c907c1/attachment.html>



More information about the Python-Dev mailing list