2012-06-18 13 views
7

In un ciclo, sto tentando di rinviare il confronto dei due valori() s di due nodi in un secondo momento.Valutazione differita con lambda in Python

class Node(): 
    def __init__(self, v): 
     self.v = v 
    def value(self): 
     return self.v 

nodes = [Node(0), Node(1), Node(2), Node(3), Node(4), Node(2)] 
results = [] 
for i in [0, 1, 2]: 
    j = i + 3 
    results.append(lambda: nodes[i].value() == nodes[j].value()) 

for result in results: 
    print result 

I risultati sono tutto vero (perché i, j == 2,5 per tutta la lambda). Come posso rinviare l'esecuzione del lambda fino a quando non viene effettivamente chiamato, ma con le associazioni di variabili corrette? E le espressioni nel lambda non sono tutte necessariamente uguaglianza ... ci sono un sacco di altre espressioni più coinvolte.

Grazie per qualsiasi aiuto!

+0

Non sono proprio sicuro di cosa stai cercando di fare. L'espressione lambda mi sembra inutile qui. Perché non puoi semplicemente fare 'results.append (nodi [i] .value() == nodi [j] .value())'? – JAB

risposta

11

Per associare i valori correnti di i e j alla funzione invece di visualizzarli nell'ambito esterno, è possibile utilizzare un valore di argomento di chiusura o di default. Il modo più semplice per farlo è quello di utilizzare i valori di default degli argomenti in lambda:

for i in [0, 1, 2]: 
    j = i + 3 
    results.append(lambda i=i, j=j: nodes[i].value() == nodes[j].value()) 

Ecco come apparirebbe come una chiusura:

def make_comp_func(i, j): 
    return lambda: nodes[i].value() == nodes[j].value() 

for i in [0, 1, 2]: 
    j = i + 3 
    results.append(make_comp_func(i, j)) 
3

Il modo idiomatica è quello di utilizzare un argomento di default:

[f() for f in [lambda: i for i in range(3)]] 
[2, 2, 2] 

Modifica questo:

[f() for f in [lambda i=i: i for i in range(3)]] 
[0, 1, 2] 
5

Avvolgere in un altro lambda:

results.append((lambda x, y: lambda: nodes[x].value() == nodes[y].value()) (i, j)) 

o in un modo più bello, con partial:

from functools import partial 

results.append(partial(lambda x, y: nodes[x].value() == nodes[y].value(), i, j)) 

default argomenti trucco è, beh ... un trucco, e io suggerirei di evitare esso.

+1

+1 per suggerire parziale. – jdi