[Python-Dev] PEP 572: Assignment Expressions

Tim Peters tim.peters at gmail.com
Tue Apr 24 12:40:42 EDT 2018


[Antoine]
> ...
> Yes... I think most will agree that Python is generally easy to take up
> for people coming from C++ etc., so my "easier to learn and teach" was
> mostly about non-programmers.

[Tim]
>> even for raw beginners the semantics are the tiniest part of what
>> they need to learn anyway about Python's assignment expressions.

> I'm not sure what you mean by that.  If it's the tiniest part, what's
> the overwhelming part?

I was hoping it was clear from context that I was talking about
"binding expressions", not the PEP's wholly general "assignment
expressions".


> Is the new assigment expression that delicate to use that it requires
> reading a long and intimidating design document ? I didn't get that
> impression, so it seems you may be making a stronger point than me
> for rejecting the PEP :-)

I'm -1 myself on the PEP's assignment expressions, because there are
no compelling use cases yet for any but the simplest ("binding
expressions") cases.  And, yes, understanding Python's assignment
statements is challenging.  Just understanding their grammar is
challenging:

assignment_stmt ::=  (target_list "=")+ (starred_expression | yield_expression)
target_list     ::=  target ("," target)* [","]
target          ::=  identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | slicing
                     | "*" target

Followed by pages of dense text explaining what all those
possibilities mean.  A binding expression is more like:

binding_expression ::= identifier ":=" expression

and the only part of the assignment statement docs needed to explain
the meaning is the brief "If the target is an identifier (name)"
section, augmented with "and the value of `expression` is the value of
the binding expression".  If someone has learned what

i = 1

means, they already learned almost all of what binding expressions
mean too.  The target in a binding expression can't be more
complicated than the `i` in that example.


>>> "await" is a more readable and less confusing improvement
>>> over "yield from".

>> Heh.  Not to me.  I have literally have no idea what to with "await"
>> (I use generators heavily, but have had no use yet for coroutines),
>> but use
>>
>>     yield from an_iterable
>>
>> routinely.

> Yeah... "yield from" is fine for that, except that it was explicitly
> meant for the coroutine use case as well (I'm not sure what the
> timeline is, but probably Guido was already thinking/dreaming about
> tulip/asyncio back then). And trying to shoehorn both in a single
> construct made it confusing and inadequate.
>
> When you want to express two abstractly different concepts (generating
> a stream of values, or suspending a task until some asynchronous subtask
> finishes), it makes things easier if those two concepts have two
> different concrete expressions. Hence "await" making the language
> easier to learn for those whose use cases benefit from it.

All of which I remain blissfully unaware of :-)


...
>> It's simply impossible that, whatever "await" does, it
>> could be more readable or less confusing than what I use "yield from"
>> for.

> Probably because "await" wouldn't work at all for you, then :-)

I'm glad people who need "await" got it - they'd have to pry _my_ uses
of "yield from" from my cold, dead fingers ;-)  Despite that all my
uses could be trivially replaced by

    for _ in an_iterable:
        yield _

"yield from" saves typing, indentation, and conceptual noise for me.
It's the "binding expressions" of nested generators ;-)


>>>  Format strings dispense from the older, more convoluted formulations.

>> But they didn't _replace_ them.  That made teaching/learning harder,
>> not easier,

> Intuitively, it sounds easier to teach f'some {value}' rather than
> either the .format() or %-formatting alternatives.  The whole goal of
> f-strings, after all, is to make string formatting more approachable.
>
> Learning a language is not learning the whole spec.  When you learn C,
> you don't need to learn the oddities of pre-ANSI function
> declarations :-)

A difference is that there still are mountains of code using earlier
string formatting methods, and my guess is that there always will be.
f-strings aren't always "better".  For example, any number of
generators (including the combinatoric generators from itertools)
yield a sequence of tuples, and

    format_string % a_tuple

is often the simplest way to format the tuple components.  Breaking
the tuple apart first, whether via explicit indexing in an f-string,
or via unpacking into a tuple of names for use in an f-string, is
often needless complication.

So % formatting needs to be learned by anyone who wants to read
_other_ peoples' code.

Then again, that's fine by me, because I don't really care whether
something new needs to be learned.  What I do care about is whether
the benefits exceed the costs of learning.


> However, assignment a special case in this regard, since traditional
> assignment is so omnipresent in online resources, that people _will_
> encounter it even if they make a very focused use of Python.

Which means absolutely everyone already understands almost everything
about the semantics of binding expressions ;-)


>>> Iteration is much simpler than the longer forms we would have to write
>> > if generalized iterators didn't exist.

>> I'll buy that one.  Now go through the HISTORY file and count all the
>> changes you didn't name ;-)

> You claimed that """almost no addition has ever made a language easier
> to learn for raw beginners""".  I claim that several additions did
> (for Python alone), but I don't need to prove that most of them did ;-)

Nor do I need to prove that "almost no" is substantially smaller than
"several" ;-)


More information about the Python-Dev mailing list