> 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(<nonlocal p>  # 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.