Comprender lambda en Python y usarlo para pasar múltiples argumentos

90

Después de leer todo lo que puedo encontrar en lambda, todavía no entiendo cómo hacer que haga lo que quiero.

Todos usan el ejemplo:

lambda x, y : x + y

¿Por qué necesita indicar ambos xy yantes del :? Además, ¿cómo se hace que devuelva múltiples argumentos?

por ejemplo:

self.buttonAdd_1 = Button(self, text='+', command=lambda : self.calculate(self.buttonOut_1.grid_info(), 1))

Esto funciona bien. Pero el siguiente código no:

self.entry_1.bind("<Return>", lambda : self.calculate(self.buttonOut_1.grid_info(), 1))

Produce el error:

TypeError: () no acepta argumentos (1 dado)

Talisin
fuente

Respuestas:

136

¿Por qué necesita indicar tanto 'x' como 'y' antes del ':'?

Porque una lambda es (conceptualmente) lo mismo que una función, simplemente escrita en línea. Tu ejemplo es equivalente a

def f(x, y) : return x + y

simplemente sin vincularlo a un nombre como f.

Además, ¿cómo se hace que devuelva múltiples argumentos?

De la misma forma que con una función. Preferiblemente, devuelve una tupla:

lambda x, y: (x+y, x-y)

O una lista, o una clase, o lo que sea.

El asunto con self.entry_1.binddebería ser respondido por Demosthenex.

phipsgabler
fuente
2
Para realmente sacarles el mínimo provecho, puede probar algo de programación funcional, que es una experiencia increíble cuando comienza a comprenderla, y probablemente lo convertirá en un mejor programador. </propaganda>
phipsgabler
3
Eres mi dios y tu propaganda es mi pan de cada día. Sin embargo, intenté aplicarlo en una tupla: (train["pred_idx_cos"],train["target"]).apply(lambda x,y: get_result(x, y))y parece que no funciona. Por favor, salva mi alma de la niebla de la programación procedimental
Revolución para Mónica
@RevolucionforMonica Una respuesta un poco tardía, pero aquí hay un ejemplo de código REPL de Python 3 de cómo hacerlo: repl.it/@foobar123/ScarceWhimsicalMainframe
Mass Dot Net
11

Creo que bind siempre intenta enviar un parámetro de evento. Tratar:

self.entry_1.bind("<Return>", lambda event: self.calculate(self.buttonOut_1.grid_info(), 1))

Acepta el parámetro y nunca lo usa.

Demosthenex
fuente
Dios mío, había estado trabajando en eso durante tanto tiempo y luego obtengo una respuesta funcional en 1 minuto plano ... Por cierto, ¿sabes por qué las cosas van delante de los dos puntos?
Talisin
2
Porque son parámetros de función .
phipsgabler
3
También puede probar "event = None" para darle un valor predeterminado, luego la función se puede usar para enlazar y el botón.
Demosthenex
5

¿Por qué necesita indicar ambos xy yantes del :?

Porque es una definición de función y necesita saber qué parámetros acepta la función y en qué orden. No puede simplemente mirar la expresión y usar los nombres de las variables en eso, porque algunos de esos nombres para los que es posible que desee usar valores de variables locales o globales existentes, e incluso si lo hiciera, no sabría en qué orden debería esperar conseguirlos.

Su mensaje de error significa que Tk está llamando a su lambda con un argumento, mientras que su lambda está escrito para no aceptar argumentos. Si no necesita el argumento, simplemente acepte uno y no lo use. ( Demosthenex tiene el código , lo habría publicado, pero me ganaron).

un poco
fuente
Gracias por la explicación. Creo que finalmente estoy entendiendo esto.
Talisin
3

¿Por qué necesita indicar tanto 'x' como 'y' antes del ':'?

De hecho, en algunas situaciones (cuando solo tiene un argumento) podría no poner xey antes de ":".

>>> flist = []
>>> for i in range(3):
...     flist.append(lambda : i)

pero la i en la lambda estará vinculada por el nombre, entonces,

>>> flist[0]()
2
>>> flist[2]()
2
>>>

diferente de lo que puede desear.

AlbertoAndreotti
fuente