2014-09-26 2 views
2

Есть ли способ распаковать кортеж с помощью идиомы * при использовании встроенного в Python map?Использование * idiom для распаковки аргументов при использовании map()

В идеале я хотел бы сделать следующее:

def foo(a, b): 
    return a**2 + b 

x = [(1,2), (3,4), (5,6)] 

results = map(foo, *x) 

, где результаты будут равны [3, 13, 31]

ответ

6

Вы ищете itertools.starmap:

def foo(a, b): 
    return a**2 + b 

x = [(1,2), (3,4), (5,6)] 

from itertools import starmap 

starmap(foo, x) 
Out[3]: <itertools.starmap at 0x7f40a8c99310> 

list(starmap(foo, x)) 
Out[4]: [3, 13, 31] 

Обратите внимание, что даже в питона 2, starmap возвращает итерируемый, который вы должны вручную потреблять с чем-то вроде list.

1

уродливее путь, чем путь в @ roippi в ...

x = [(1,2), (3,4), (5,6)] 

map(lambda y:y[0]**2 + y[1], x) 
1

Как это происходит, map принимает * арг, поэтому ваш первоначальный вызов map(foo, *x) не сразу неудачи - но то, что происходит в том, что каждый элемент от x рассматривается как последовательность значений для одного аргумента до foo - поэтому он пытается выполнить foo(1, 3, 5) и затем попытается выполнить foo(2, 4, 6), за исключением того, что foo принимает только 2 аргумента.

Поскольку мы можем видеть, что наш вклад x фактически является «транспонированная матрица», что мы хотели бы питаться в, что прямо указывает нам на обходной путь:

>>> list(map(foo, *zip(*x))) # list() wrapping for 3.x support 
[3, 13, 31] 

... Но не сделай это. Использовать itertools.starmap; он построен для этого и значительно более четко о ваших намерениях.

Смежные вопросы