Pythonic way to append output of function to sever

2019-07-26 14:39发布

I have a question that I haven't quite found a good solution to. I'm looking for a better way to append function output to two or more lists, without using temp variables. Example below:

def f():
  return 5,6

a,b = [], []
for i in range(10):
  tmp_a, tmp_b = f()
  a.append(tmp_a)
  b.append(temp_b)

I've tried playing around with something like zip(*f()), but haven't quite found a solution that way. Any way to remove those temp vars would be super helpful though, thanks!

Edit for additional info: In this situation, the number of outputs from the function will always equal the number of lists that are being appended to. The main reason I'm looking to get rid of temps is for the case where there are maybe 8-10 function outputs, and having that many temp variables would get messy (though I don't really even like having two).

4条回答
【Aperson】
2楼-- · 2019-07-26 15:21

First solution: we make a list of all results, then transpose it

def f(i):
    return i, 2*i

# First make a list of all your results
l = [f(i) for i in range(5)]
# [(0, 0), (1, 2), (2, 4), (3, 6), (4, 8)]

# then transpose it using zip
a, b = zip(*l)

print(list(a))
print(list(b))
# [0, 1, 2, 3, 4]
# [0, 2, 4, 6, 8]

Or, all in one line:

a, b = zip(*[f(i) for i in range(5)])

A different solution, building the lists at each iteration, so that you can use them while they're being built:

def f(i):
    return 2*i, i**2, i**3

doubles = []
squares = []
cubes = []
results = [doubles, squares, cubes]

for i in range(1, 4):
    list(map(lambda res, val: res.append(val), results, f(i)))
    print(results)

# [[2], [1], [1]]
# [[2, 4], [1, 4], [1, 8]]
# [[2, 4, 6], [1, 4, 9], [1, 8, 27]]

print(cubes)
# [1, 8, 27]

Note about list(map(...)): in Python3, map returns a generator, so we must use it if we want the lambda to be executed.list does it.

查看更多
相关推荐>>
3楼-- · 2019-07-26 15:22
def f():
    return 5,6

a,b = zip(*[f() for i in range(10)])
# this will create two tuples of elements 5 and 6 you can change 
# them to list by type casting it like list(a), list(b)
查看更多
爷的心禁止访问
4楼-- · 2019-07-26 15:40

I'd do

tmp = f()
a.append(tmp[0])
b.append(tmp[1])

Not sure how pythonic it is for you though.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-07-26 15:43

For your specific case, the zip answers are great.

Using itertools.cycle and itertools.chain is a different approach from the existing answers that might come in handy if you have a lot of pre-existing lists that you want to append to in a round-robin fashion. It also works when your function returns more values than you have lists.

>>> from itertools import cycle, chain
>>> a, b = [], [] # new, empty lists only for demo purposes
>>> for l, v in zip(cycle([a, b]), (chain(*(f() for i in range(10))))):
...     l.append(v)
... 
>>> a
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
>>> b
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6]
查看更多
登录 后发表回答