[Python-Dev] PEP 572: Assignment Expressions -- intention to accept, near-final draft

Guido van Rossum guido at python.org
Tue Jul 10 00:15:37 EDT 2018


On Mon, Jul 9, 2018 at 8:24 PM, Rob Cliffe via Python-Dev <
python-dev at python.org> wrote:

> I apologise for not replying in the form of a Pull Request - I don't know
> how to make one.
>
>
> On 10/07/2018 02:00, Guido van Rossum wrote:
>
>> Rationale
>> =========
>>
>> Naming the result of an expression is an important part of programming,
>> allowing a descriptive name to be used in place of a longer expression,
>> and permitting reuse.  Currently, this feature is available only in
>> statement form, making it unavailable in list comprehensions and other
>> expression contexts.
>>
>

> I think the wording of the last sentence gives too much importance to list
> comprehensions (IMO influenced by the amount of discussion of the PEP that
> was related to list comprehensions, understandably since that was the case
> where the semantics were most debatable).  I would suggest
> "... making it unavailable in expression contexts."
> or maybe
> "... making it unavailable in expression contexts (including list
> comprehension)."
>

Hm, I don't think it's worth tweaking the text here. The PEP has some
choice things to say about comprehensions, and I don't mind calling them
out especially here. Also, when you need a temporary variable outside a
comprehension it's easy enough to rewrite the code a bit -- but for a
comprehension you'd have to refactor the whole comprehension away (into a
regular for-loop), which is a bit more effort.



> Another example illustrates that programmers sometimes do more work to
>> save an extra level of indentation::
>>
>>     match1 = pattern1.match(data)
>>     match2 = pattern2.match(data)
>>     if match1:
>>         return match1.group(1)
>>     elif match2:
>>         return match2.group(2)
>>
>> This code tries to match ``pattern2`` even if ``pattern1`` has a match
>> (in which case the match on ``pattern2`` is never used). The more
>> efficient rewrite would have been::
>>
>>     match1 = pattern1.match(data)
>>     if match1:
>>         return match1.group(1)
>>     else:
>>         match2 = pattern2.match(data)
>>         if match2:
>>             return match2.group(2)
>>
> I suggest
> ... The more efficient rewrite would have been:
>     match1 = pattern1.match(data)
>     if match1:
>         return match1.group(1)
>     match2 = pattern2.match(data)
>     if match2:
>         return match2.group(2)
> (a more natural way to write it which avoids cascading indentation).
>

Hm, I think I might have simplified this a bit from the code I actually
found -- there might not have been a `return` in the original. I don't want
to break the `if...elif` pattern in the rewrite. I guess I'll rewrite it
using assignment to a variable instead of `return`.


>     # Handle a matched regex
>>     if (match := pattern.search(data)) is not None:
>>         ...
>>
> I suggest
>     # Handle a matched regex
>     if (match := pattern.search(data)) is not None:
>         # do something with match
> I think it is really important to make clear the benefit of the PEP here:
> that "match" is bound to a value and can be used subsequently.
>
>     # A more explicit alternative to the 2-arg form of iter() invocation
>>     while (value := read_next_item()) is not None:
>>         ...
>>
> As the 2-arg form of iter() is not that well known, I suggest that the
> iter version is spelled out for contrast.  (Sorry, I can't quite work it
> what it would be.)
>

Hm, you have a point there. I was referring to

  for value in iter(read_next_item, None):
      ...

The example would be more convincing if there was an additional argument to
read_next_value(), since then the 2-arg iter() version would have required
a lambda. Maybe I shouldn't mention 2-arg iter here at all.


>     # Share a subexpression between a comprehension filter clause and its
>> output
>>     filtered_data = [y for x in data if (y := f(x)) is not None]
>>
> That's fine, but what about also having an example that illustrates,
> simply, the "permitting reuse" in an expression part of the Rationale, e.g.
>         powers = [ (y := x+1), y**2, y**3, y**4 ]
> (I appreciate that this sort of overlaps with the section "Simplifying
> list comprehensions", but it seems to me to be such an important part of
> the Rationale that it should be illustrated here.)
>

I could add this (before the filtered_data example):

    # Reuse a value that's expensive to compute
    [y := f(x), y**2, y**3]



> Relative precedence of ``:=``
>> -----------------------------
>>
>> The ``:=`` operator groups more tightly than a comma in all syntactic
>> positions where it is legal, but less tightly than all operators,
>> including ``or``, ``and`` and ``not``.
>>
> and presumably including "if" and "else", as in
>     x := y if y else -1
> Might it be worth adding "if" and "else" to the list?
>

Good call, I'll add conditional expressions to the list.


> - Single assignment targets other than than a single ``NAME`` are
>>   not supported::
>>
>>     # No equivalent
>>     a[i] = x
>>     self.rest = []
>>
>> [snip]
>>
>> - Iterable packing and unpacking (both regular or extended forms) are
>>   not supported::
>>
>>     # Equivalent needs extra parentheses
>>     loc = x, y  # Use (loc := (x, y))
>>     info = name, phone, *rest  # Use (info := (name, phone, *rest))
>>
>>     # No equivalent
>>     px, py, pz = position
>>     name, phone, email, *other_info = contact
>>
>> [snip]
>>     total += tax  # Equivalent: (total := total + tax)
>>
> Is it conceivable that some of these restrictions might be removed in a
> future version of Python?  If so, the PEP might include a note to this
> effect.
>

I wouldn't hold my breath.


> Oh, and what I think are typos:
>
> (Note that ``with EXPR as VAR`` does *not* simply assing the value
>    of ``EXPR`` to ``VAR`` -- it calls ``EXPR.__enter__()`` and assigns
>    the result of *that* to ``VAR``.)
>
>     assing -> assign
>

Fixed already.

(eg where the condition is ``f(x) < 0``
>
>     eg -> e.g.
>

Thanks, will fix.


> members of the core-mentorship mailing list
>
>     core-mentorship -> core mentorship
>

Why? The list is named core-mentorship at python.org.


> is a vast improvment over the briefer::
>
>     improvment -> improvement
>

Will fix.


> Best wishes
> Rob Cliffe
>

https://github.com/python/peps/pull/719

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180709/c9ab5a21/attachment-0001.html>


More information about the Python-Dev mailing list