I have the following expression:
>>> a = 3
>>> b = 2
>>> a == (a := b)
False
Now, a == 2
after the operation, as expected. And the result is what I would want, i.e., comparison of a
to RHS of assignment before assignment.
Reversing the order of the equality operator reverses the result:
>>> a = 3
>>> b = 2
>>> (a := b) == a
True
There does not appear to be anything directly relevant to this corner case in PEP-572, relative precedence section. The next section, change to evaluation order mentions that the evaluation order is left-to-right. Is that what is going on here (stash the value of a
, update it, and compare vs update a
, then compare against its new value)?
Where is this behavior defined, and how reliable is it?
Neither of those PEP sections have to do with this. You just have a
==
comparison, and the general Evaluation order applies: "Python evaluates expressions from left to right."So your
(a := b) == a
simply first evaluates the left side(a := b)
, assigning something toa
and evaluating to the same value. And then evaluate the right sidea
, which is of course still the same (just-assigned) value, so you getTrue
.About those PEP sections:
What that first PEP section says is that
:=
groups less tightly than==
, so it would apply if you didn't have parentheses:a == a := b
would mean(a == a) := b
(you'd get a syntax error for trying to assign to a comparison).a := b == a
would meana := (b == a)
, where with your values theb == a
evaluates toFalse
and that gets assigned toa
and becomes the result of the entire expression. (Note that at statement-level, you'd have to write(a := b == a)
.)What that second PEP section does is just to point out something bad that had already existed but which the
:=
made "more visible", so they suggested to finally fix it. The issue was that a dict comprehension like{X: Y for ...}
evaluatedY
beforeX
, against the general left-to-right rule and against dict displays like{X: Y}
which already did evaluateX
beforeY
as expected. Consider this:With that old behavior, it would've resulted in
{2: 2}
. And given that people might write something like that when:=
became available, it became more of an issue.