<br><br>On Wednesday, April 25, 2018, Łukasz Langa <<a href="mailto:lukasz@langa.pl">lukasz@langa.pl</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><br><div><blockquote type="cite"><div>On 25 Apr, 2018, at 5:20 PM, Chris Angelico <<a href="mailto:rosuav@gmail.com" target="_blank">rosuav@gmail.com</a>> wrote:</div><br><div><div>On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov<br><<a href="mailto:yselivanov.ml@gmail.com" target="_blank">yselivanov.ml@gmail.com</a>> wrote:<br><blockquote type="cite">Just yesterday this snippet was used on python-dev to show how great the<br>new syntax is:<br><br>          my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))<br><br>To my eye this is an anti-pattern.  One line of code was saved, but the<br>other line becomes less readable.  The fact that 'buf' can be used after<br>that line means that it will be harder for a reader to trace the origin of<br>the variable, as a top-level "buf = " statement would be more visible.<br></blockquote><br>Making 'buf' more visible is ONLY a virtue if it's going to be used<br>elsewhere. Otherwise, the name 'buf' is an implementation detail of<br>the fact that this function wants both a buffer and a size.</div></div></blockquote><br></div><div><div>You're claiming that `:=` is nicer in this situation because it's less</div><div>prominent than regular assignment and thus doesn't suggest that the name</div><div>stays visible later.</div><div><br></div><div>But as others said, `:=` *does* make the name visible later until the</div><div>enclosing scope ends.  In fact, a large part of its appeal is that you</div><div>can use the result later (as in the `re.search()` example).  Will it be</div><div>visible enough to the reaser in those cases then?</div><div><br></div><div>There seems to be a conflict there.</div><div><br></div><div>The question of assignment visibility also makes me think about</div><div>unintentional name shadowing::</div><div><br></div><div><font face="Courier New">    buf = some_value</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">    ...  # 20 lines</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">    my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">    ...  # 20 lines</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">    buf  # <-- What value does this have?</font></div><div><br></div><div><br></div><div>Even if we're not using the call pattern, there can be plenty of logic</div><div>tests which aren't very obvious::</div><div><br></div><div><font face="Courier New">    buf = some_value</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">    ...  # 20 lines</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">    if node.parent is not None and (buf := node.parent.buffer):</font></div><div><font face="Courier New">        ... # 10 lines</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">    ...  # 20 lines</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">    buf  # <-- What value does this have?</font></div><div><br></div><div><br></div><div>This is even more interesting because now `buf` isn't rebound</div><div>*always*.</div><div><br></div><div>So if I'm confused about an unexpected change in value of `buf`, I'll</div><div>skim the code, fail to find the assignment, and then grep for `buf =`</div><div>and also fail to find the assignment.  Yes, I could have searched for</div><div>just `buf` instead but that will give me too many false positives,</div><div>especially if I'm using a primitive text editor search or don't know</div><div>about \b in regular expressions.</div><div><br></div><div>Debugging this can be confusing.  I know it can since a similar</div><div>annoyance can be observed with the magic pseudo-scope of `except`::</div><div><br></div><div><font face="Courier New">    err = some_value</font></div><div><font face="Courier New">    try:</font></div><div><font face="Courier New">        ...</font></div><div><font face="Courier New">    except Error as err:</font></div><div><font face="Courier New">        ...</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">    err  # <-- now sometimes it's not defined</font></div><div><br></div><div><br></div><div>Just like Barry, I debugged a few cases of this in the past and within</div><div>larger functions this can be hard to find.</div></div></div></blockquote><div><br></div><div>Would this make it easier to put too much code on one line?</div><div><br></div><div>Is there a good way to get *branch coverage* stats instead of just *line coverage*?</div><div><br></div><div>Someone can probably explain with some tested pretty code for me why this would be necessary or helpful; why it wouldn't make line coverage stats more misleading for the sake of lazy?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><div><br></div><div>-- Ł</div><div><br></div></div></div></blockquote>