2013-06-01 5 views
14

Я знаю, чтоPython `map` и аргументы распаковка

map(function, arguments) 

эквивалентно

for argument in arguments: 
    function(argument) 

Можно ли использовать функцию карты, чтобы сделать следующее?

for arg, kwargs in arguments: 
    function(arg, **kwargs) 
+1

Эти две вещи не являются эквивалент. 'map()' строит список (или в 3.x, генератор) возвращаемых значений из вызовов функций. Если вы не хотите использовать эти значения, не используйте 'map()', просто используйте обычный цикл. –

+5

'map' - это функция (которая возвращает список), а цикл - это код без возвращаемого значения. Они не эквивалентны. –

ответ

16

Вы можете с лямбда:

map(lambda a: function(a[0], **a[1]), arguments) 

или вы могли бы использовать выражение генератор или список понимание, в зависимости от того, что вы хотите:

(function(a, **k) for a, k in arguments) 
[function(a, **k) for a, k in arguments] 

В Python 2, map() возвращается список (таким образом, понимание списка эквивалентно), в Python 3, map() является генератором (поэтому выражение генератора может заменить его).

Не существует встроенного или стандартного метода библиотеки, который делает это напрямую; прецедент слишком специализирован.

0

Вы просто должны помнить, что карта передаст аргументы функции как один кортеж, а не отдельные аргументы. Если вы не можете изменить первоначальную функцию, вы можете вызвать его с помощью вспомогательной функции:

def f(tup): 
    args, kwargs = tup 
    function(args, **kwargs) 

map(f, arguments) 
7

Для случая только позиционных аргументов, вы можете использовать itertools.starmap(fun, args):

Возврат итератор, значение возвращаются из функции, оцененной с помощью кортежа аргументов, взятого из данной последовательности.

Пример:

from itertools import starmap 

def f(i, arg): 
    print(arg * (i+1)) 

for _ in starmap(f, enumerate(["a", "b", "c"])): 
    pass 

печатает:

a 
bb 
ccc 
0

я продолжал работать в одной и той же потребности, и в конечном итоге сделать следующие функции:

def kwarg_map(element_constructor, **kwarg_lists): 
    """ 
    A helper function for when you want to construct a chain of objects with individual arguments for each one. Can 
    be easier to read than a list expansion. 

    :param element_constructor: A function of the form object = fcn(**kwargs) 
    :param kwarg_lists: A dict of lists, where the index identifies two which element its corresponding value will go. 
    :return: A list of objects. 

    e.g. Initializing a chain of layers: 
     layer_sizes = [784, 240, 240, 10] 
     layers = kwarg_map(
      Layer, 
      n_in = layer_sizes[:-1], 
      n_out = layer_sizes[1:], 
      activation = ['tanh', 'tanh', 'softmax'], 
      ) 

    is equivalent to: 
     layers = [Layer(n_in=784, n_out=240, activation='tanh'), Layer(n_in=240, n_out=240, activation='tanh'), Layer(n_in=240, n_out=10, activation='softmax')] 
    """ 
    all_lens = [len(v) for v in kwarg_lists.values()] 
    assert len(kwarg_lists)>0, "You need to specify at least list of arguments (otherwise you don't need this function)" 
    n_elements = all_lens[0] 
    assert all(n_elements == le for le in all_lens), 'Inconsistent lengths: %s' % (all_lens,) 
    return [element_constructor(**{k: v[i] for k, v in kwarg_lists.iteritems()}) for i in xrange(n_elements)] 
Смежные вопросы