<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Jun 28, 2018 at 9:28 AM, Tim Peters <span dir="ltr"><<a href="mailto:tim.peters@gmail.com" target="_blank">tim.peters@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div dir="ltr">>>> g = (x:=i for i in range(3))<br></div></div><div class="gmail_quote">Common or not, I have no idea why anyone would write a genexp like the one you gave, except to contrive an example of silly behavior exhibited by silly code ;-)<br></div></div></blockquote><div><br></div><div>yes, it was a contrived example, but the simplest one I could think of off the top of my head that re-bound a name in the loop -- which was what I thought was the entire point of this discussion?</div><div><br></div><div>If we think hardly anyone is ever going to do that -- then I guess it doesn't matter how it's handled.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><span>> So while this is technically the same as the comprehension, it is not<br>> the same as a generator function which does get its own scope.</span></div><div class="gmail_quote"><br></div><div class="gmail_quote">It is the same as a generator function with appropriate scope declarations - a generator expression is, after all, implemented _by_ a nested generator function. You can write a workalike to your code above today, but nobody worries about that because nobody does that ;-)</div><div class="gmail_quote"><br></div><div class="gmail_quote"><div class="gmail_quote"> def f():</div><div class="gmail_quote"> def bashx(outermost):</div><div class="gmail_quote"> nonlocal x</div><div class="gmail_quote"> for i in outermost:</div><div class="gmail_quote"> x = i</div><div class="gmail_quote"> yield i</div></div></div></blockquote><div><br></div><div>but here the keyword "nonlocal" is used -- you are clearly declaring that you are messing with a nonlocal name here -- that is a lot more obvious than simply using a :=</div><div><br></div><div>And "nonlocal" is not used that often, and when it is it's for careful closure trickery -- I'm guessing := will be far more common. And, of course, when a newbie encounters it, they can google it and see what it means -- far different that seeing a := in a comprehension and understanding (by osmosis??) that it might make changes in the local scope.</div><div><br></div><div>And I don't think you can even do that with generator expressions now -- as they can only contain expressions. Which is my point -- this would allow the local namespace to be manipulated in places it never could before.</div><div><br></div><div>Maybe it's only comprehensions, and maybe it'll be rare to have a confusing version of those, so it'll be no big deal, but this thread started talking about educators' take on this -- and as an educator, I think this really does complicate the language.</div><div><br></div><div>Python got much of it's "fame" by being "executable pseudo code" -- its been moving farther and farther away from those roots. That's generally a good thing, as we've gain expressiveness in exchangel, but we shouldn't pretend it isn't happening, or that this proposal doesn't contribute to that trend.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote">Did adding ternary `if` (truepart if expression else falsepart) complicate the language significantly? </div></div></blockquote><div><br></div><div>I don't think so -- no. For two reasons:</div><div><br></div><div>1) the final chosen form is kind of verbose, but therefor more like "executable pseudo code" :-) As apposed to the C version, for instance.</div><div> </div><div>2) it added one new construct, that if, when someone sees it for the first (or twenty fifth) time and doesn't understand it, they can look it up, and find out. and it only effects that line of code.</div><div><br></div><div>So adding ANYTHING does complicate the language, by simply making it a bit larger, but some things are far more complicating than others.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"> Python has rarely expanded the number of expression forms, but whenever it has the sky didn't actually fall despite earnest warnings that disaster was inevitable ;-)</div></div></blockquote><div><br></div><div>Well, I've been surprised by what confused students before, and I will again. But I dont hink there is any doubt that Python 3.7 is a notably harder to learn that Python 1.5 was...</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><span>> Maybe it’s just me, but re-binding a name seems like a whole new<br>> category of side effect.<br><br></span>With no trickery at all, you've always been able to rebind attributes, and mutate containers, in comprehensions and genexps. Because `for` targets aren't limited to plain names; e.g.,</div><div class="gmail_quote"><br></div><div class="gmail_quote"> g = (x+y for object.attribute, a[i][j] in zip(range(3), range(3)))<br></div></div></blockquote><div><br></div><div>sure, but you are explicitly using the names "object" and "a" here -- so while side effects in comprehension are discouraged, it's not really a surprised that namespaces specifically named are changed.</div><div><br></div><div>and this:</div><div><br></div><div>
<span></span>
<p class="gmail-p1" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:normal;font-family:Menlo;color:rgb(52,163,39);background-color:rgb(255,255,255)"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">In [</span><span class="gmail-s2" style="font-variant-ligatures:no-common-ligatures;color:rgb(46,231,33)"><b>55</b></span><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">]: </span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">x = </span><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">0</span></p>
<p class="gmail-p2" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:normal;font-family:Menlo;color:rgb(0,0,0);background-color:rgb(255,255,255);min-height:18px"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p class="gmail-p1" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:normal;font-family:Menlo;color:rgb(52,163,39);background-color:rgb(255,255,255)"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">In [</span><span class="gmail-s2" style="font-variant-ligatures:no-common-ligatures;color:rgb(46,231,33)"><b>56</b></span><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">]: </span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">[x </span><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures"><b>for</b></span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)"> x </span><span class="gmail-s4" style="font-variant-ligatures:no-common-ligatures;color:rgb(208,59,255)"><b>in</b></span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)"> </span><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">range</span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">(</span><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">3</span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">)]</span></p>
<p class="gmail-p3" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:normal;font-family:Menlo;color:rgb(0,0,0);background-color:rgb(255,255,255)"><span class="gmail-s5" style="font-variant-ligatures:no-common-ligatures;color:rgb(178,54,34)">Out[</span><span class="gmail-s6" style="font-variant-ligatures:no-common-ligatures;color:rgb(255,59,30)"><b>56</b></span><span class="gmail-s5" style="font-variant-ligatures:no-common-ligatures;color:rgb(178,54,34)">]: </span><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">[0, 1, 2]</span></p>
<p class="gmail-p2" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:normal;font-family:Menlo;color:rgb(0,0,0);background-color:rgb(255,255,255);min-height:18px"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p class="gmail-p1" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:normal;font-family:Menlo;color:rgb(52,163,39);background-color:rgb(255,255,255)"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">In [</span><span class="gmail-s2" style="font-variant-ligatures:no-common-ligatures;color:rgb(46,231,33)"><b>57</b></span><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">]: </span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">x</span></p>
<p class="gmail-p4" style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:normal;font-family:Menlo;color:rgb(178,54,34);background-color:rgb(255,255,255)"><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">Out[</span><span class="gmail-s6" style="font-variant-ligatures:no-common-ligatures;color:rgb(255,59,30)"><b>57</b></span><span class="gmail-s1" style="font-variant-ligatures:no-common-ligatures">]: </span><span class="gmail-s3" style="font-variant-ligatures:no-common-ligatures;color:rgb(0,0,0)">0</span></p>
<br></div><div>doesn't change x in the local scope -- if that was a good idea, why is a good idea to have := in a comprehension effect the local scope??</div><div><br></div><div>But maybe it is just me.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote">And as in my goofy code above, mucking with binding of plain names is also possible today. Indeed, straightforward if that's what you _want_ to do. But nobody does.<br><br>It's just not one of Python's goals to make it impossible to write useless code ;-)<br></div></div></blockquote><div><br></div><div> I suppose we need to go back and look at the "real" examples of where/how folks think they'll use := in comprehensions, and see how confusing it may be.</div><div><br></div><div>One of these conversations was started with an example something like this:</div><font face="monospace, monospace"><br>[(f(x), g(f(x))) for x in an_iterable]</font><div>
<br></div><div>The OP didn't like having to call f() twice. So that would become:</div><div><br></div><div><font face="monospace, monospace">[ (temp:=f(x), g(temp)) for x in an_iterable]</font></div><div><br></div><div>so now the question is: should "temp" be created / changed in the enclosing local scope?</div><div><br></div><div>This sure looks a lot like letting the iteration name (x in this example) leak out -- so I'd say no.</div><div><br></div><div>And I don't think this kind of thing would be rare.</div><div><br></div><div>Someone mentions that one problem with letting the iteration name leak out is that people tend to use short, common names, like "i" -- Im thinking that would also be the case for this kind of temp variable.</div><div><br></div><div><br></div><div>-CHB</div><div> </div></div><br><br clear="all"><div><br></div>-- <br><div class="m_-7015734023117811399m_-6660068262497242047gmail_signature" data-smartmail="gmail_signature"><br>Christopher Barker, Ph.D.<br>Oceanographer<br><br>Emergency Response Division<br>NOAA/NOS/OR&R (206) 526-6959 voice<br>7600 Sand Point Way NE (206) 526-6329 fax<br>Seattle, WA 98115 (206) 526-6317 main reception<br><br><a href="mailto:Chris.Barker@noaa.gov" target="_blank">Chris.Barker@noaa.gov</a></div>
</div></div>