On Fri, Aug 9, 2019 at 9:03 AM Peter O'Connor <peter.ed.ocon...@gmail.com>
wrote:

> Alright hear me out here:
>
> I've often found that it would be useful for the following type of
> expression to be condensed to a one-liner:
>
> def running_average(x_seq):
>     averages = []
>     avg = 0
>     for t, x in enumerate(x_seq):
>         avg =  avg*t/(t+1) + x/(t+1)
>         averages.append(avg)
>     return averages
>
> Because really, there's only one line doing the heavy lifting here, the
> rest is kind of boilerplate.
>

But it's boilerplate that communicates the starting state of your loop
which is useful to know and to have be very clearly communicated.


>
> Then I learned about the beautiful and terrible "for x in [value]":
>
> def running_average(x_seq):
>     return [avg for avg in [0] for t, x in enumerate(x_seq) for avg in
> [avg*t/(t+1) + x/(t+1)]]
>
> Many people find this objectionable because it looks like there are 3 for
> loops, but really there's only one: loops 0 and 2 are actually assignments.
>
> **My Proposal**
>
> What if we just officially bless this "using for as a temporary
> assignment" arrangement, and allow "for x=value" to mean "assign within the
> scope of this for".  It would be identical to "for x in [value]", just more
> readable.  The running average function would then be:
>
> def running_average(x_seq):
>     return [avg for avg=0 for t, x in enumerate(x_seq) for avg = avg *
> t/(t+1) + x / (t+1)]
>

I personally don't find that more readable then the unrolled version you're
trying to avoid. And based on the amount of grief we got for the walrus
operator I wouldn't expect much uptake on this as being considered more
readable by others either. (And remember that "Readability counts").

-Brett


>
> ------ P.S. 1
> I am aware of Python 3.8's new "walrus" operator, which would make it:
>
> def running_average(x_seq):
>     avg = 0
>     return [avg := avg*t/(t+1) + x / (t+1) for t, x in enumerate(x_seq)]
>
> But it seems ugly and bug-prone to be initializing a in-comprehension
> variable OUTSIDE the comprehension.
>
> ------ P.S. 2
> The "for x = value" syntax can achieve things that are not nicely
> achievable using the := walrus.  Consider the following example (wherein we
> carry forward a "hidden" variable h but do not return it):
>
> y_seq = [y for h=0 for x in x_seq for y, h = update(x, h)]
>
> There's not really a nice way to do this with the walrus because you can't
> (as far as I understand) combine it with tuple-unpacking.  You'd have to do
> something awkward like:
>
> yh = None, 0
> y_seq, _ = zip(*(yh := update(x, yh[1]) for x in x_seq))
> ------
>
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/RHW5AUV3C57YOF3REB2HEMYLWLLXSNQT/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/J7FQP2KPODR4LA5K7HCLYU547O7CHHEV/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to