<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Jul 9, 2018 at 8:24 PM, Rob Cliffe via Python-Dev <span dir="ltr"><<a href="mailto:python-dev@python.org" target="_blank">python-dev@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I apologise for not replying in the form of a Pull Request - I don't know how to make one.<span class="gmail-"><br>
<br>
<br>
On 10/07/2018 02:00, Guido van Rossum wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Rationale<br>
=========<br>
<br>
Naming the result of an expression is an important part of programming,<br>
allowing a descriptive name to be used in place of a longer expression,<br>
and permitting reuse. Currently, this feature is available only in<br>
statement form, making it unavailable in list comprehensions and other<br>
expression contexts.<br></blockquote></span></blockquote><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
</blockquote></span>
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<br>
"... making it unavailable in expression contexts."<br>
or maybe<br>
"... making it unavailable in expression contexts (including list comprehension)."<span class="gmail-"><br></span></blockquote><div><br></div><div>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.<br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Another example illustrates that programmers sometimes do more work to<br>
save an extra level of indentation::<br>
<br>
match1 = pattern1.match(data)<br>
match2 = pattern2.match(data)<br>
if match1:<br>
return match1.group(1)<br>
elif match2:<br>
return match2.group(2)<br>
<br>
This code tries to match ``pattern2`` even if ``pattern1`` has a match<br>
(in which case the match on ``pattern2`` is never used). The more<br>
efficient rewrite would have been::<br>
<br>
match1 = pattern1.match(data)<br>
if match1:<br>
return match1.group(1)<br>
else:<br>
match2 = pattern2.match(data)<br>
if match2:<br>
return match2.group(2)<br>
</blockquote></span>
I suggest<br>
... The more efficient rewrite would have been:<span class="gmail-"><br>
match1 = pattern1.match(data)<br>
if match1:<br>
return match1.group(1)<br></span><span class="gmail-">
match2 = pattern2.match(data)<br>
if match2:<br>
return match2.group(2)<br></span>
(a more natural way to write it which avoids cascading indentation).<span class="gmail-"><br></span></blockquote><div><br></div><div>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`.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
# Handle a matched regex<br>
if (match := pattern.search(data)) is not None:<br>
...<br>
</blockquote></span>
I suggest<span class="gmail-"><br>
# Handle a matched regex<br>
if (match := pattern.search(data)) is not None:<br></span>
# do something with match<br>
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.<span class="gmail-"><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
# A more explicit alternative to the 2-arg form of iter() invocation<br>
while (value := read_next_item()) is not None:<br>
...<br>
</blockquote></span>
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.)<span class="gmail-"><br></span></blockquote><div><br></div><div>Hm, you have a point there. I was referring to</div><div><br></div><div> for value in iter(read_next_item, None):</div><div> ...</div><div><br></div><div>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.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
# Share a subexpression between a comprehension filter clause and its output<br>
filtered_data = [y for x in data if (y := f(x)) is not None]<br>
</blockquote></span>
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.<br>
powers = [ (y := x+1), y**2, y**3, y**4 ]<br>
(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.)<span class="gmail-"><br></span></blockquote><div><br></div><div>I could add this (before the filtered_data example):</div><div><br></div><div> # Reuse a value that's expensive to compute<br> [y := f(x), y**2, y**3]<br><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Relative precedence of ``:=``<br>
-----------------------------<br>
<br>
The ``:=`` operator groups more tightly than a comma in all syntactic<br>
positions where it is legal, but less tightly than all operators,<br>
including ``or``, ``and`` and ``not``.<br>
</blockquote></span>
and presumably including "if" and "else", as in<br>
x := y if y else -1<br>
Might it be worth adding "if" and "else" to the list?<br></blockquote><div><br></div><div>Good call, I'll add conditional expressions to the list.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
- Single assignment targets other than than a single ``NAME`` are<br>
not supported::<br>
<br>
# No equivalent<br>
a[i] = x<br>
self.rest = []<br>
<br></span>
[snip]<span class="gmail-"><br>
<br>
- Iterable packing and unpacking (both regular or extended forms) are<br>
not supported::<br>
<br>
# Equivalent needs extra parentheses<br>
loc = x, y # Use (loc := (x, y))<br>
info = name, phone, *rest # Use (info := (name, phone, *rest))<br>
<br>
# No equivalent<br>
px, py, pz = position<br>
name, phone, email, *other_info = contact<br>
<br></span>
[snip]<span class="gmail-"><br>
total += tax # Equivalent: (total := total + tax)<br>
</span></blockquote>
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.<br></blockquote><div><br></div><div>I wouldn't hold my breath.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Oh, and what I think are typos:<span class="gmail-"><br>
<br>
(Note that ``with EXPR as VAR`` does *not* simply assing the value<br>
of ``EXPR`` to ``VAR`` -- it calls ``EXPR.__enter__()`` and assigns<br>
the result of *that* to ``VAR``.)<br>
<br></span>
assing -> assign<span class="gmail-"><br></span></blockquote><div><br></div><div>Fixed already.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
(eg where the condition is ``f(x) < 0``<br>
<br></span>
eg -> e.g.<span class="gmail-"><br></span></blockquote><div><br></div><div>Thanks, will fix.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
members of the core-mentorship mailing list<br>
<br></span>
core-mentorship -> core mentorship<span class="gmail-"><br></span></blockquote><div><br></div><div>Why? The list is named <a href="mailto:core-mentorship@python.org">core-mentorship@python.org</a>.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">
is a vast improvment over the briefer::<br>
<br></span>
improvment -> improvement<br></blockquote><div><br></div><div>Will fix.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Best wishes<br>
Rob Cliffe<br></blockquote><div><br></div><div><a href="https://github.com/python/peps/pull/719">https://github.com/python/peps/pull/719</a><br></div></div><br>-- <br><div class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div></div>