1

Can we shorter this code without using := because my python version is lower than 3.8?

arr = [3,2,1,0]
ml = .7
arrSum = 0
res = []
for a in reversed(arr):
    arrSum = a + ml*arrSum
    res.append(arrSum)
res[::-1]
# [4.89, 2.7, 1.0, 0.0]

with :=:

>>> arrSum = 0
>>> [arrSum := a + ml*arrSum for a in reversed(arr)][::-1]
[4.89, 2.7, 1.0, 0.0]

It's Okay If solution be with numpy or ... .

RanN
  • 59
  • 8

2 Answers2

2

You can use e.g. itertools:

from itertools import accumulate

ml = 0.7
arr = [3, 2, 1, 0]
list(accumulate(arr[::-1], lambda x,y: ml * x + y))[::-1] 

It gives:

[4.89, 2.7, 1.0, 0]

numpy is another option:

import numpy as np

np.convolve(ml**np.arange(len(arr)), arr[::-1])[len(arr)-1::-1]
bb1
  • 7,174
  • 2
  • 8
  • 23
1
arrSum = 0
[arrSum := a + ml*arrSum for a in reversed(arr)][::-1]

could be rewritten as

arrsum = 0

def fn(x):
   nonlocal arrsum   # or 'global arrsum' depending on the context
   arrsum = x
   return x

[fn(a + ml*arrSum) for a in reversed(arr)][::-1]

Not saying that it is a good idea to do this ... but this is a direct way to simulate := in an earlier Python version.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • `arrsum` needs to be declared as `global` in `fn`. – bb1 Dec 12 '21 at 06:32
  • Actually ... `nonlocal` may be better in this example. It depends on whether `arrsum` is *really* a global variable or not. – Stephen C Dec 12 '21 at 06:40
  • 1
    Another way to maintain state is to exploit a [mutable default argument](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument). Or use e.g. `functools.partial` to bind a mutable object as an argument explicitly. Or use a class. – Karl Knechtel Dec 12 '21 at 06:47
  • Thanks a lot, very well explanation – RanN Jul 26 '22 at 18:11