<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Sat, Jul 7, 2018 at 5:48 PM Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Enforcing such restrictions in the grammar would actually be complicated, due to nesting -- but even if it wasn't, I wouldn't want to, as I don't want to limit future generations to only the benefits of the new construct that we can now come up with. Orthogonality is a good thing in my mind, else we might never have had nested functions or conditional imports.<br></div></div></blockquote><div><br></div><div>Got it.</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"><div dir="ltr"><div>As to why you might want to use := in a function call, I could imagine writing</div><div><br></div><div>    if validate(name := re.search(pattern, line).group(1)):</div><div>        return name</div></div></blockquote><div><br></div><div>I meant this case:</div><div><br></div><div>    >>> foo(x := 1)   # execute "x = 1" AND "foo(1)" </div><div><br></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">I find that (space between the <span style="text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">parentheses of a </span>function call statement) too unnatural as a place where to put an assignment</span>. It is not even "guarded" by a keyword like "if" or  "while" which can help as indicators that an assignment may occur. Also, I think it's way too easy to confuse it with a keyword argument:</div><div><br></div><div>    >>> foo(x = 1)  # keyword arg</div><div>    >>> foo(x := 1)  # assignment + value passing</div><div><br></div><div>As for "assert" what I'm concern about is the proliferation of things like this:</div><div><div style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"> </div></div><div><div>    class Foo:</div><div>        def __init__(self):</div><div>            assert self.x := fun1()</div><div>            assert self.y := fun2()</div><div>            assert self.z := fun3()</div><div><br></div></div><div>When I look at that my brain tells me that the main subject of the line is "assert", not the assignment, but maybe it's just because I'm not used to it. That aside there's the question of what to do when "python -O" switch is used. With this in place "-O" would acquire a new meaning, as it would disable "assert" statements AND assignments.</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"><div class="gmail_quote"><div dir="ltr">On Sat, Jul 7, 2018 at 6:12 AM Giampaolo Rodola' <<a href="mailto:g.rodola@gmail.com" target="_blank">g.rodola@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div>Sorry in advance for opening yet another topic about PEP-572. With PEP-572 being officially accepted I know debating its inclusion in the language is a useless exercise at this point, but since it's still in "draft" status I would like to express my opinion as I think this is a feature which can potentially be abused fairly easily. FWIW I initially found myself disliking the idea as a whole but <a href="https://github.com/python/cpython/pull/8122" target="_blank">https://github.com/python/cpython/pull/8122</a> made me (and others) reconsider it quite a bit (see: <a href="https://twitter.com/grodola/status/1015251302350245888" target="_blank">https://twitter.com/grodola/status/1015251302350245888</a>). PR-8122 clearly shows an improvement in expressiveness and compactness (many folks argue this is too much) but PEP-572 as it currently stands is too permissive IMHO. My concern about "easily abusable ugly cases" still remains, and I think they should be banned instead of just discouraged in the PEP or in the doc. Since we spend way more time *reading* code rather than writing it, as a "reader" I would expect a more prudent approach to the problem.</div><div><br></div><div>Proposal</div><div>========</div><div><br></div><div>1) allow only one := assignment per line in "if" statements:</div><div>    >>> if x := val1 and y := val2:   # SyntaxError or SyntaxWarning</div><div>    >>> if x == val1 and y := val2:   # SyntaxError or SyntaxWarning</div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">    >>> if x := val1 and y == val2:   # SyntaxError or SyntaxWarning</span></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">    >>> if x := val1:  # OK</span></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">    >>> if (x := val1):  # OK</span><br></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div>2) allow := in "while" statements, "if" statements and comprehensions only:</div><div>    >>> foo(x := 0)  # SyntaxError</div><div>    >>> yield x := 3  # SyntaxError</div><div>    >>> assert y := 3  # SyntaxError</div><div><br></div><div>3) (debatable) disallow := if the variable is already defined:</div><div>    >>> x = 5</div><div>    >>> if (x := val):  # SyntaxError or SyntaxWarning</div><div><br></div><div>4) ban "a = (b := c)", "x = a := (b := (c := d))" and similar (they're just too ugly IMHO)</div><div><br></div><div>Rationale 1</div><div>===========</div><div><br></div><div>In visual terms assignments in Python have always occurred at the BEGINNING of the line and always on the most LEFT side:</div><div><br></div><div>    >>> foo = fun1()</div><div>    >>> bar = fun2()</div><div>    >>> baz = fun3()</div><div><br></div><div>That is where I naturally expect an assignment to be when reading code. My main concern with PEP-572 is that an assignments can now occur at *any point* in the line:</div><div><br></div><div>    >>> foo = fun1()</div><div>    >>> bar = fun2()</div><div>    >>> if foo == val1 and bar == val2 and baz := fun3():</div><div>    ...    ...</div><div><br></div><div>That forces me to visually scan the whole line horizontally from left to right 'till its end, looking for possible variables being set. I'm co # execute "foo(1)" AND "x = 1"ncerned that I will miss := occurrences because visually they are very similar to == unless parentheses are made mandatory:</div><div><br></div><div>    >>> if foo == val1 and bar == val2 and (baz := fun3()):</div><div>    ...    ...</div><div><br></div><div>Also, in case of multi-line conditionals I have to visually scan the construct both horizontally AND vertically:</div><div><br></div><div>    >>> if (foo == val1 and \</div><div>    ...        bar == val2 and \</div><div>    ...        baz := val3):</div><div>    ...     ...</div><div><br></div><div>Again, that is not a place where I would expect to find or look for a variable assignment. I know I wouldn't like to read or review a code which does that and I suspect linters will likely end up wanting to emit a warning in that case (see: <a href="https://github.com/PyCQA/pylint/issues/2246" target="_blank">https://github.com/PyCQA/pylint/issues/2246</a>). <a href="https://github.com/python/cpython/pull/8116/files" target="_blank">https://github.com/python/cpython/pull/8116/files</a> avoids using multiple := per line and that's why the result appears readable enough IMO. </div><div><br></div><div>Rationale 2</div><div>===========</div><div><br></div><div>PEP-572 states:</div><div><br></div><div>    > The := operator may be used directly in a positional function call argument</div><div><br></div><div>That means allowing:</div><div><br></div><div>    >>> foo(x := 0)</div><div><br></div><div>I honestly don't see why anyone would want to call a function AND assign a variable value at the same time (except in comprehensions). With this in place I not only have to guard against "if" statements assigning values at any point in the code, but also function calls, both horizontally and vertically e.g.:</div><div><br></div><div>    >>> foo(some_long_var_name, another_one, x := bar(),</div><div>            y := fun())</div><div><br></div><div>To me this looks like the perfect example of where this functionality can be abused. Also, I'm not clear what PEP-572 intend to do about "all other places". E.g. should these cases be allowed? (IMO no)</div><div><br></div><div>    >>> yield x := 3</div><div>    >>> assert y := 3</div><div><br></div><div>--</div><div>Giampaolo - <a href="http://grodola.blogspot.com" target="_blank">http://grodola.blogspot.com</a></div></div><div><br></div></div>
_______________________________________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org" target="_blank">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/guido%40python.org" rel="noreferrer" target="_blank">https://mail.python.org/mailman/options/python-dev/guido%40python.org</a><br>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr" class="gmail-m_-8660642482779257131gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>Giampaolo - <a href="http://grodola.blogspot.com" target="_blank">http://grodola.blogspot.com</a></div><div><br></div></div></div></div>