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 to a
and evaluating to the same value. And then evaluate the right side a
, which is of course still the same (just-assigned) value, so you get True
.
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 mean a := (b == a)
, where with your values the b == a
evaluates to False
and that gets assigned to a
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 ...}
evaluated Y
before X
, against the general left-to-right rule and against dict displays like {X: Y}
which already did evaluate X
before Y
as expected. Consider this:
>>> a, b = 3, 2
>>> {a: (a := b) for _ in '_'}
{3: 2}
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.