[Python-Dev] PEP 572: Assignment Expressions

Ethan Furman ethan at stoneleaf.us
Mon Apr 23 16:01:21 EDT 2018


On 04/22/2018 10:44 PM, Tim Peters wrote:
> [Guido]
>> In reality there often are other conditions being applied to the match for
>> which `if expr as name` is inadequate. The simplest would be something like
>>
>>    if ...:
>>        <something>
>>    elif (m := re.match('(.*):(.*)', line)) and m.group(1) == m.group(2):
>>      <whatever>
>>
>> And the match() call may not even be the first thing to check -- e.g. we
>> could have
>>
>>      elif line is not None and (m := re.match('(.*):(.*)', line)) and m.group(1) == m.group(2):
>
> I find myself warming more to binding expressions the more I keep them
> in mind while writing new code.  And I think it may be helpful to
> continue showing real examples where they would help.
>
> Today's example:  I happened to code this a few hours ago:
>
> diff = x - x_base
> if diff:
>      g = gcd(diff, n)
>      if g > 1:
>          return g
>
> It's not really hard to follow, but two levels of nesting "feels
> excessive", as does using the names "diff" and "g" three times each.
> It's _really_ an "and" test:  if the diff isn't 0 and gcd(diff, n) >
> 1, return the gcd.  That's how I _thought_ of it from the start.
>
> Which this alternative expresses directly:
>
> if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
>      return g

So I really like being able to make the assignment in the expression, but I have a really hard time parsing it with the 
name first.

Attempting to read just the names first:

   if
     diff
       scan for ending right paren
       found
   and
      g
       scan for ending right paren
         oops, found opening left paren
         scan for ending right paren
         found
       resume scanning for final right paren
       found
      > 1:
          return g


Attempting to read expressions first:

   if
     x - x_base
   and
     gcd(diff, n)
       what's diff?
         scan backwards
           diff is x - x_base
     > 1:
         return g
           what's g?
             scan up and backwards
             g is gcd(diff, n)


Attempting to read interleaved:

   if
     skip diff
       x - x_base
       back to diff
     as diff
   and
     skip g
       gcd(diff, n)
       back to g
     as g
   > 1:
       return g


On the other hand, if it were using the "as" keyword:

if (x - xbase as diff) and (gcd(diff, n) as g) > 1:
     return g

I would parse as:

   if
     x - x_base
     as diff
   and
     gcd(diff, n)
     as g
   > 1:
       return g

For me at least, the last is much more readable.  Thinking about it some more, the problem (or maybe just my problem) is 
that I see an "if" or "while" and the I look for the thing that is True or False, and using the ":=" syntax the first 
thing I see is a placeholder for a result that doesn't exist yet, making me constantly scan backwards and forwards to 
put all the pieces in the correct place.

With "as", it just flows forwards.

--
~Ethan~


More information about the Python-Dev mailing list