[Python-Dev] PEP 572: Assignment Expressions
Christoph Groth
christoph at grothesque.org
Thu Apr 19 19:27:29 EDT 2018
I'd like to break a lance for PEP 572.
I read that in the bad old days Python used to have a "=" operator in
expressions that had the meaning of today's "==". Perhaps there were
other reasons, but this choice alone meant that assignment (that was
using the same token) could not be made an expression.
When the equality comparison operator was changed to "==", nothing
changed for assignments which remained statements.
Let's imagine, just for a moment, that Python is redesigned from
scratch. Would it make sense to make assignment an expression? (For
clarity an operator that is different from "=" would be used, say ":=".)
I would say that the answer to the above question depends on whether
assignment expressions can (a) fully replace assignment statements
(so that both don't need to coexist) and (b) are useful and not too
prone to abuse. I will try to answer both questions separately.
----------------
It seems to me that assignment expressions can be defined in a way that
is fully analogous with the assignment statements of today's Python (and
that consequently is equivalent in confusion potential):
The "value" of any assignment statement from today's Python can be
defined as the value that will be captured when "__value__ =" is prepended
to that statement.
So what should be the value of 'result' after the following snippet?
a := list()
b := list()
result := (a[:] := b[:] := iter(range(3)))
It seems to me that it should be the same as with today's
result = a[:] = b[:] = iter(range(3))
Accepting this convention would mean that parens in assignment
expressions would behave differently from C. For example
result := (a[:] := (b[:] := iter(range(3))))
would produce a different 'result'. But I think that's OK, just like
it's OK that the Python expression
-1 < 0 < 1
is not equivalent to
(-1 < 0) < 1
----------------
The question remains whether assignment expressions are actually useful
and not too prone to abuse? I think that the situation is similar to
the "or" and "and" operators when used for their values. The snippet
value = dic.get(key) or default
could be replaced by an if clause, so there's no "one obvious way to do
it" here. Still, many will agree that the above one-liner is nicer and
more expressive. It wouldn't be possible if there were no boolean
expressions and the use of "or" was limited to within if and while
statements.
In a similar way assignment expressions have many uses that are not
absolutely needed but make code more expressive. The danger of abuse is
also similar to "and" and "or" where it's also possible to write
expressions that are difficult to understand.
Here's an example from real life where the existence of assignment
expressions would crucially simplify an API. I'm working on a library
that has "learners" that are driven by "runners". The simplest possible
synchronous runner looks like this:
def sync_runner(learner, f, static_hint):
while True:
points = learner.get(static_hint)
if not points:
break
learner.feed(f(points))
(Note that more advanced runners supply a "hint" that dynamically
depends on currently available resources for example.)
With assignment expressions the body of the above function could be
simplified to
while points := learner.get(static_hint):
learner.feed(f(points))
making it crucially simpler. Using the learner API becomes so natural
that a 'sync_runner()' function seems not even necessary. This API
could be even adopted by other learner-providing libraries that want to
support being driven by advanced asynchronous runners but would like to
remain easily usable directly.
Surely there are other uses of similar idioms.
----------------
Perhaps you agree with me that assignment should be an expression if
Python was to be redesigned from scratch, but that is not going to
happen. But couldn't Python simply introduce ":=" as described above
and keep "=" for backwards compatibility?
New users of Python could by taught to use ":=" everywhere. Old users
could either convert their code base, or ignore the addition. There's
no problem in mixing both old and new style code.
Like with other expressive features, there's potential for confusion,
but I think that it's limited. Wouldn't it be a pity not to liberate
assignments from their boring statement existence?
Cheers,
Christoph
More information about the Python-Dev
mailing list