[Python-Dev] PEP 572: Assignment Expressions

Chris Angelico rosuav at gmail.com
Fri Apr 20 22:30:36 EDT 2018


On Sat, Apr 21, 2018 at 11:38 AM, Anthony Flury via Python-Dev
<python-dev at python.org> wrote:
> I am entirely new to this list, but if I can I would like share my comments
> :
>
>  * I do think this proposal <target> := <value> has merit in my
>    opinion; it does make some code more readable.
>
>  * I think readability is only improved if :

There's that word "readability" again. Sometimes I wish the Zen of
Python didn't use it, because everyone seems to think that "readable"
means "code I like".

>  * The current expectations of how comprehensions work should also be
>    honored; I don't claim to have fully followed all of the discussions
>    around this, but it seems to me that comprehensions work in a
>    particular way because of a concerted effect (especially in Python
>    3) to make them that way. They are self contained and don't leak
>    values in their containing scope. Similarly I think that setting
>    variables within a comprehension is just for the benefit of readable
>    code within the comprehension - i.e. :
>
>                 stuff = [[y, x/y] for x in range(5) for y in [f(x)]]
>
>                 can become :
>
> stuff = [[y := f(x), x/y] for x in range(5)]
>
> So - overall from me a conditional +1 - conditions as above; if they are not
> possible then -1 from me.

Perfectly self-contained. They do everything in their own scope.
Except ... except that they don't.

$ python3.7
Python 3.7.0a4+ (heads/master:95e4d58913, Jan 27 2018, 06:21:05)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class X:
...     x = ["spam", "ham"]
...     print(["1: "+x for x in x])
...     print(["2: "+x for _ in range(1) for x in x])
...
['1: spam', '1: ham']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in X
  File "<stdin>", line 4, in <listcomp>
UnboundLocalError: local variable 'x' referenced before assignment
>>> class Y:
...     prefix = "3: "
...     print([prefix + x for x in ["spam", "ham"]])
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in Y
  File "<stdin>", line 3, in <listcomp>
NameError: name 'prefix' is not defined

Introducing expression assignments will make these oddities even more
obvious. You'd be able to demonstrate things like this at function
scope, not just with a class. But the oddities are there, and they are
inherent to the current definition of a comprehension. That's why the
changes are being recommended. They will simplify the peculiarities of
comprehensions, make them far closer to a naive transformation into
longhand, and extremely close to a non-naive-but-still-simple
transformation into longhand.

ChrisA


More information about the Python-Dev mailing list