2013-06-01 3 views
14

so, chePython `map` e argomenti disimballaggio

map(function, arguments) 

è equivalente a

for argument in arguments: 
    function(argument) 

è possibile utilizzare la funzione mappa per effettuare le seguenti operazioni?

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

Queste due cose non sono equivalente. 'map()' crea una lista (o in 3.x, un generatore) dei valori restituiti dalle chiamate di funzione. Se non vuoi usare quei valori, non usare 'map()', usa solo un ciclo normale. –

+5

'map' è una funzione (che restituisce una lista) e il ciclo è un codice senza valore di ritorno. Non sono equivalenti. –

risposta

16

È possibile con un lambda:

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

o si potrebbe usare un generatore di espressione o di lista, a seconda di ciò che si vuole:

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

In Python 2, map() rendimenti una lista (quindi la list comprehension è l'equivalente), in Python 3, map() è un generatore (quindi l'espressione del generatore può sostituirlo).

Non esiste un metodo di libreria standard o incorporato che lo faccia direttamente; il caso d'uso è troppo specializzato.

0

Devi solo ricordare che la mappa passerà gli argomenti alla funzione come una tupla anziché argomenti separati. Se non è possibile modificare la funzione originaria, si può chiamare con una funzione di supporto:

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

map(f, arguments) 
7

Per il caso di soli argomenti posizionali, è possibile utilizzare itertools.starmap(fun, args):

Ritorna un iteratore i cui valori vengono restituiti dalla funzione valutata con un argomento tupla tratto dalla sequenza data.

Esempio:

from itertools import starmap 

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

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

stampe:

a 
bb 
ccc 
0

ho continuato a correre nella stessa esigenza e finito per fare la seguente funzione:

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)]