<div dir="auto">I continue to find all this weird new syntax to create absurdly long one-liners confusing and mysterious. Python is not Perl for a reason.</div><br><div class="gmail_quote"><div dir="ltr">On Mon, Apr 9, 2018, 5:55 PM Peter O'Connor <<a href="mailto:peter.ed.oconnor@gmail.com">peter.ed.oconnor@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Kyle, you sounded so reasonable when you were trashing itertools.accumulate (which I now agree is horrible).  But then you go and support Serhiy's madness: <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255);float:none;display:inline"> </span><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255);font-size:12.8px">"smooth_signal = [</span><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255);font-size:12.8px">average </span><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255);font-size:12.8px">for average in [0]</span><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255);font-size:12.8px"> for x in signal</span><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255);font-size:12.8px"> for average in [(1-decay)*average + decay*x]</span><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255);font-size:12.8px">]" which I agree is clever, but reads more like a riddle than readable code.  </span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;background-color:rgb(255,255,255);font-size:12.8px"><br></span></div><div>Anyway, I continue to stand by:</div><div><br></div><div>    (y:= f(y, x) for x in iter_x from y=initial_y)</div><div><br></div><div>And, if that's not offensive enough, to its extension:</div><div><br></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">    (z, y := f(z, x) -> y for x in iter_x from z=initial_z)</span><br></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Which carries state "z" forward but only yields "y" at each iteration.  (see proposal: <a href="https://github.com/petered/peps/blob/master/pep-9999.rst" style="color:rgb(17,85,204);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)" target="_blank" rel="noreferrer">https://github.com/petered/peps/blob/master/pep-9999.rst</a>)</span></div><div><br></div><div>Why am I so obsessed?  Because it will allow you to conveniently replace classes with more clean, concise, functional code.  People who thought they never needed such a construct may suddenly start finding it indispensable once they get used to it.  </div><div><br></div><div>How many times have you written something of the form?:</div><div><br></div><div><div>    class StatefulThing(object):</div><div>    </div><div>        def __init__(self, initial_state, param_1, param_2):</div><div>            self._param_1= param_1 </div><div>            self._param_2 = param_2 </div><div>            self._state = initial_state</div><div>    </div><div>        def update_and_get_output(self, new_observation):  # (or just __call__)</div><div>            self._state = do_some_state_update(self._state, <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">new_observation</span>, self._param_1) </div><div>            output = transform_state_to_output(self._state, self._param_2)</div><div>            return <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">output</span></div><div>    </div><div>    processor = StatefulThing(initial_state = initial_state, param_1 = 1, param_2 = 4)</div><div>    processed_things = [processor.<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">update_and_get_output</span>(x) for x in x_gen]</div><div>    </div></div><div>I've done this many times.  Video encoding, robot controllers, neural networks, any iterative machine learning algorithm, and probably lots of things I don't know about - they all tend to have this general form.  </div><div><br></div><div>And how many times have I had issues like "Oh no now I want to change param_1 on the fly instead of just setting it on initialization, I guess I have to refactor all usages of this class to pass param_1 into <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">update_and_get_output</span> instead of __init__".  </div><div><br></div><div>What if instead I could just write:</div><div><br></div><div>    def <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">update_and_get_output(last_state, <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">new_observation, param_1, param_2)</span></span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">        new_state = do_some_state_update(<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">last_state</span>,<span> </span><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">new_observation</span>, _param_1) </div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">        output = transform_state_to_output(<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">last_state</span>, _param_2)</div></span></span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">        return new_state, output</span></span></div><div><br></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">    processed_things</span> = [state, output:= <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">update_and_get_output(state, x, param_1=1, param_2=4) -> output for x in observations from state=initial_state] </span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">Now we have:</span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">- No mutable objects (<span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">which cuts of a whole slew of potential bugs and anti-patterns familiar to people who do OOP.) </span></span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">- Fewer lines of code</span></span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">- Looser assumptions on usage and less refactoring. (if I want to now pass in param_1 at each iteration instead of just initialization, I need to make no changes to <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">update_and_get_output).</span></span></span></div><div>- No need for state getters/setters, since state is is passed around explicitly.</div><div></div><div><br></div><div>I realize that calling for changes to syntax is a lot to ask - but I still believe that the main objections to this syntax would also have been raised as objections to the now-ubiquitous list-comprehensions - they seem hostile and alien-looking at first, but very lovable once you get used to them.  </div><div><br></div><div><span style="font-size:12.8px"><br></span></div><div><br></div><div><br></div><div class="gmail_extra"><div class="gmail_quote">On Sun, Apr 8, 2018 at 1:41 PM, Kyle Lahnakoski <span dir="ltr"><<a href="mailto:klahnakoski@mozilla.com" target="_blank" rel="noreferrer">klahnakoski@mozilla.com</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"><span class="m_1446131339724817613m_-5016113561075346744m_-3757572314863908047gmail-m_3455230515993595352m_-3053248010740228130gmail-"><br>
<br>
On 2018-04-05 21:18, Steven D'Aprano wrote:<br>
> (I don't understand why so many people have such an aversion to writing<br>
> functions and seek to eliminate them from their code.)<br>
><br>
<br>
</span>I think I am one of those people that have an aversion to writing functions!<br>
<br>
I hope you do not mind that I attempt to explain my aversion here. I<br>
want to clarify my thoughts on this, and maybe others will find<br>
something useful in this explanation, maybe someone has wise words for<br>
me. I think this is relevant to python-ideas because someone with this<br>
aversion will make different language suggestions than those that don't.<br>
<br>
Here is why I have an aversion to writing functions: Every unread<br>
function represents multiple unknowns in the code. Every function adds<br>
to code complexity by mapping an inaccurate name to specific<br>
functionality. <br>
<br>
When I read code, this is what I see:<br>
<br>
>    x = you_will_never_guess_how_corner_cases_are_handled(a, b, c)<br>
>    y =<br>
you_dont_know_I_throw_a_BaseException_when_I_do_not_like_your_arguments(j,<br>
k, l)<br>
<br>
Not everyone sees code this way: I see people read method calls, make a<br>
number of wild assumptions about how those methods work, AND THEY ARE<br>
CORRECT!  How do they do it!?  It is as if there are some unspoken<br>
convention about how code should work that's opaque to me.<br>
<br>
For example before I read the docs on<br>
itertools.accumulate(list_of_length_N, func), here are the unknowns I see:<br>
<br>
* Does it return N, or N-1 values?<br>
* How are initial conditions handled?<br>
* Must `func` perform the initialization by accepting just one<br>
parameter, and accumulate with more-than-one parameter?<br>
* If `func` is a binary function, and `accumulate` returns N values,<br>
what's the Nth value?<br>
* if `func` is a non-cummutative binary function, what order are the<br>
arguments passed? <br>
* Maybe accumulate expects func(*args)?<br>
* Is there a window size? Is it equal to the number of arguments of `func`?<br>
<br>
These are not all answered by reading the docs, they are answered by<br>
reading the code. The code tells me the first value is a special case;<br>
the first parameter of `func` is the accumulated `total`; `func` is<br>
applied in order; and an iterator is returned.  Despite all my<br>
questions, notice I missed asking what `accumulate` returns? It is the<br>
unknown unknowns that get me most.<br>
<br>
So, `itertools.accumulate` is a kinda-inaccurate name given to a<br>
specific functionality: Not a problem on its own, and even delightfully<br>
useful if I need it often. <br>
<br>
What if I am in a domain where I see `accumulate` only a few times a<br>
year? Or how about a program that uses `accumulate` in only one place?<br>
For me, I must (re)read the `accumulate` source (or run the caller<br>
through the debugger) before I know what the code is doing. In these<br>
cases I advocate for in-lining the function code to remove these<br>
unknowns. Instead of an inaccurate name, there is explicit code. If we<br>
are lucky, that explicit code follows idioms that make the increased<br>
verbosity easier to read.<br>
<br>
Consider Serhiy Storchaka's elegant solution, which I reformatted for<br>
readability<br>
<span class="m_1446131339724817613m_-5016113561075346744m_-3757572314863908047gmail-m_3455230515993595352m_-3053248010740228130gmail-"><br>
> smooth_signal = [<br>
>     average<br>
>     for average in [0]<br>
>     for x in signal<br>
>     for average in [(1-decay)*average + decay*x]<br>
> ]<br>
<br>
</span>We see the initial conditions, we see the primary function, we see how<br>
the accumulation happens, we see the number of returned values, and we<br>
see it's a list. It is a compact, easy read, from top to bottom. Yes, we<br>
must know `for x in [y]` is an idiom for assignment, but we can reuse<br>
that knowledge in all our other list comprehensions.  So, in the<br>
specific case of this Reduce-Map thread, I would advocate using the list<br>
comprehension. <br>
<br>
In general, all functions introduce non-trivial code debt: This debt is<br>
worth it if the function is used enough; but, in single-use or rare-use<br>
cases, functions can obfuscate.<br>
<br>
<br>
<br>
Thank you for your time.<br>
<div class="m_1446131339724817613m_-5016113561075346744m_-3757572314863908047gmail-m_3455230515993595352m_-3053248010740228130gmail-HOEnZb"><div class="m_1446131339724817613m_-5016113561075346744m_-3757572314863908047gmail-m_3455230515993595352m_-3053248010740228130gmail-h5"><br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank" rel="noreferrer">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</div></div></blockquote></div><br></div><div class="gmail_extra"><br></div><div class="gmail_extra"><br></div></div>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank" rel="noreferrer">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote></div>