2015-06-02 11 views
5

ho trovato un po 'la funzione abbastanza intelligente che prende due funzioni, si applica uno sopra l'altro dato un argomento x:Perché questo lambda richiede * arg, che differenza fa?

def compose(f,g): 
    return lambda *x: f(g(*x)) 

Ora il mio problema è con *x, come io non lo vedo realmente facendo qualsiasi cosa qui Perché non potrebbe essere semplice x (senza l'asterisco)?

Qui sono le mie prove:

>>> def compose(f,g): 
... return lambda *x: f(g(*x)) 
... 
>>> this = lambda i: i+1 
>>> that = lambda b: b+1 
>>> compose(this,that)(2) 
4 

>>> def compose(f,g): 
... return lambda x: f(g(x)) 
... 
>>> compose(this,that)(2) 
4 

>>> def compose(f,g): 
... return lambda *x: f(g(*x)) 
... 
>>> compose(this,that)(2,2) 
TypeError: <lambda>() takes exactly 1 argument (2 given) 
+4

@jonrsharpe mentre spiega '*'/'**' - Non penso che spieghi il contesto di questa domanda –

risposta

4

Se g (that nei test) può anche prendere un numero variabile di argomenti, quindi lambda *x: f(g(*x)) può essere utile.

Altrimenti, non così tanto.

L'obiettivo è consentire che la funzione composta venga invocata con qualsiasi numero di argomenti e che tutti questi argomenti vengano passati alla funzione interna nella composizione.

+3

Ad esempio: compose (abs, min) (1,2, -5, -3, - 6,12, -9) – dexgecko

1

Il problema con i tuoi test è che le funzioni di composizione this e that accettare solo un singolo argomento, in modo che il punto della * nella funzione compose è perso (e si riceve un "prende esattamente 1 argomento" errore) .

Il potere dell'operatore * diventa evidente quando si desidera passare a tuple decompressi, e le vostre lambda sostenere questo:

Prova questa semplice mappa ridurre esempio:

this = lambda *i: *[x**2 for x in i] # map tuple i 
that = lambda *b: sum(b) # reduce tuple b 

def compose(f,g): 
    return lambda *x: f(*g(*x)) 

compose(that,this)(2,2) 
3

Per completare @ risposta di Frederic , sarebbe più flessibile se compose utilizzato lo standard *args, **kwargs construct:

def compose(f,g): 
    return lambda *args, **kwargs: f(g(*args, **kwargs)) 

in questo modo, compose funziona con qualsiasi funzione g, indipendentemente dalla firma di g.

Quello nella tua domanda utilizza solo la prima parte, ovvero lo *args e utilizza un nome diverso (non convenzionale) per questo, *x.

Problemi correlati