2011-09-25 13 views
20

Eventuali duplicati:
What do (lambda) function closures capture in Python?
lambda function don't closure the parameter in Python?Creazione lambda all'interno di un ciclo

Sto cercando di creare lambda all'interno di un ciclo che itera su un elenco di oggetti:

lambdas_list = [] 
for obj in obj_list: 
    lambdas_list.append(lambda : obj.some_var) 

Ora, se iterare sopra i lambda elencarli e chiamarli in questo modo:

for f in lambdas_list: 
    print f() 

Ottengo lo stesso valore. Questo è il valore dell'ultimo obj in obj_list poiché quella era l'ultima variabile nel blocco dell'iteratore di elenco. Qualche idea per una buona (pitonica) riscrittura del codice per farlo funzionare?

+1

vedere http://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python/2295372#2295372 e http://stackoverflow.com/questions/7514093/lambda -funzione-dont-chiusura-la-parametro-in-python. –

+0

risposta più descrittiva: http://stackoverflow.com/questions/938429/scope-of-python-lambda-functions-and-their-parameters/938493#938493 –

risposta

22

Utilizzare questa linea invece:

lambdas_list.append(lambda obj=obj: obj.some_var) 
+0

Più elegante dell'utilizzo di un parziale. – zoujyjs

4

si può fare qualcosa di simile:

def build_lambda(obj): 
    return lambda : obj.some_var 

lambdas_list = [] 
for obj in obj_list: 
    lambdas_list.append(build_lambda(obj)) 
8

O si deve acquisire la variabile utilizzando assegnazioni di default

lambdas_list = [ lambda i=o: i.some_var for o in obj_list ] 

o R, utilizzare tappi per catturare la variabile

lambdas_list = [ (lambda a: lambda: a.some_var)(o) for o in obj_list ] 

In entrambi i casi la chiave è quello di assicurarsi che ogni valore della lista obj_list viene assegnato a un ambito unico.

La soluzione non ha funzionato perché la variabile lessicale obj è referenziata dall'ambito padre (for).

L'assegnazione di default ha funzionato perché facciamo riferimento a i dall'ambito lambda. Usiamo l'assegnazione di default per rendere "passante" la variabile implicita rendendola parte della definizione lambda e quindi del suo ambito.

La soluzione di chiusura funziona perché la variabile "passaggio" è esplicito, nella esterna lambda che è immediatamente eseguita, creando così il legame durante la lista comprensione e ritorno e l'interno lambda che fa riferimento quello che lega. Pertanto, quando l'interno di lambda viene effettivamente eseguito, farà riferimento all'associazione creata nello scope esterno lambda.

Problemi correlati