[Python-Dev] PEP 572: Assignment Expressions

Glenn Linderman v+python at g.nevcal.com
Mon Apr 23 18:45:59 EDT 2018


On 4/23/2018 1:01 PM, Ethan Furman wrote:
> 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.

You need to borrow the time machine, and get with those early 
mathematicians that first said:

Let x be the sum of y and z

and convince them that what they should have said was:

Let the sum of y and z be called x.

:)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180423/eeeff09c/attachment.html>


More information about the Python-Dev mailing list