2012-06-18 22 views
7

En un ciclo, estoy tratando de diferir la comparación de los dos valores() de dos nodos para un momento posterior.Evaluación diferida con lambda en 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 

Los resultados son todos verdaderos (porque i, j == 2,5 para todas las lambdas). ¿Cómo puedo diferir la ejecución de la lambda hasta que realmente se llame, pero con los enlaces de variable correctos? Y las expresiones en el lambda no son necesariamente necesariamente igualdad ... hay un montón de otras expresiones más involucradas.

¡Gracias por cualquier ayuda!

+0

No estoy muy seguro de lo que estás tratando de hacer. La expresión lambda me parece innecesaria aquí. ¿Por qué no puedes hacer 'results.append (nodes [i] .value() == nodes [j] .value())'? – JAB

Respuesta

11

Para vincular los valores actuales de i y j a la función en lugar de que se vea en el ámbito externo, puede utilizar un cierre o valores de argumento predeterminados. La forma más sencilla de hacerlo es utilizar valores de los argumentos por defecto en su lambda:

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

Aquí es cómo se vería como un cierre:

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

La forma idiomática es utilizar un argumento por defecto:

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

Cambiar esto a:

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

Envolver en otro lambda:

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

o de una manera más agradable, con partial:

from functools import partial 

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

defecto argumentos truco es, bueno ... un truco, y me gustaría sugerir para evitar eso.

+1

+1 para sugerir parcial. – jdi

Cuestiones relacionadas