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/