On Sat, May 12, 2018 at 02:37:20AM +0100, Rob Cliffe via Python-ideas wrote:
> Yeah, well, I'm totally lost. Even after trying out this code, and > refactoring it once if not twice, I didn't understand it. I don't know > what point you're trying to prove, but you seem to have comprehensively > proved it. Do you mean Serhiy's example of currently supported syntax? smooth_signal = [average for average in [0] for x in signal for average in [(1-decay)*average + decay*x]] It helps if you know the algorithm for exponential smoothing: for each value x (aside from the first), the average is equal to a mix of the current value x and the previous average A, split by some proportion P: A = (1-P)*A + P*x If P is 0.5, that is equivalent to taking the ordinary average between the current value and the previous average: A = (A+x)/2 # when P == 0.5 In the comprehension, P is called "decay" and A is called "average": average = (1-decay)*average + decay*x Writing the comprehension as a single line is hard to read. Let's give it some structure: smooth_signal = [average # append average to the results for average in [0] for x in signal for average in [(1-decay)*average + decay*x] ] Horrible as it is, it is perfectly legal Python right now. It uses for name in SINGLE_ITEM_LIST to perform an assignment. So that's equivalent to: average = 0 for x in signal average = (1-decay)*average + decay*x append average to the results Pull the initial value of average out of the comprehension, and use the PEP 572 syntax: average = 0 smooth_signal = [(average := (1-decay)*average + decay*x) for x in signal] which is a huge improvement in my opinion. It would be more obvious if the expression being calculated came first: smooth_signal = [(1-decay)*average + decay*x as average for x in signal] but there are good reasons why the "as" syntax won't work. So it looks like we're stuck with needing to look ahead past the := to see the actual value being appended to the list. A minor inconvenience, equivalent to that in ternary if, where we have to look ahead to see the condition: [target := COMPREHENSION_VALUE for x in sequence] true_value if CONDITION else false_value So I expect that it will take me a little while to learn to look ahead and read binding-expressions fluently. (Like comprehensions themselves, really. It took me a few months to stop needing to pull them apart to understand them.) He's Nick's version, as best as I am able to tell: average = 0 smooth_signal = [(average given average = (1-decay)*average + decay*x) for x in signal] So we have the same look-ahead needed to see the expression we care about, but instead of merely having two characters := needed to do the binding, we need "given average =". -- Steve _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/