Una lambda es una función anónima de una sola expresión. Python las permite, pero la comunidad tiene opiniones claras sobre cuándo usarlas y cuándo definir un def normal. Usarlas correctamente mejora la legibilidad; usarlas mal produce código difícil de depurar.
Sintaxis básica
# Función normal
def cuadrado(x):
return x ** 2
# Lambda equivalente
cuadrado = lambda x: x ** 2
print(cuadrado(5)) # 25
# Lambda con múltiples parámetros
producto = lambda x, y: x * y
print(producto(3, 4)) # 12
Usos idiomáticos: sorted(), filter() y map()
El caso más frecuente es pasar una lambda como parámetro key a sorted():
personas = [
{"nombre": "Ana", "edad": 28},
{"nombre": "Luis", "edad": 22},
{"nombre": "María", "edad": 35},
]
# Ordenar por edad
por_edad = sorted(personas, key=lambda p: p["edad"])
# Ordenar por nombre descendente
por_nombre = sorted(personas, key=lambda p: p["nombre"], reverse=True)
# Ordenar tuplas por el segundo elemento
pares = [(1, 'b'), (3, 'a'), (2, 'c')]
print(sorted(pares, key=lambda t: t[1])) # [(3, 'a'), (1, 'b'), (2, 'c')]
Lambdas con filter() y map()
numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # filter() devuelve iterador con los que cumplen la condición pares = list(filter(lambda x: x % 2 == 0, numeros)) print(pares) # [2, 4, 6, 8, 10] # map() transforma cada elemento cuadrados = list(map(lambda x: x ** 2, numeros)) print(cuadrados) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] # Alternativa con comprehension (más legible para muchos) pares_c = [x for x in numeros if x % 2 == 0] cuadrados_c = [x ** 2 for x in numeros]
Lambdas en closures
def multiplicador(factor):
return lambda x: x * factor
doble = multiplicador(2)
triple = multiplicador(3)
print(doble(5)) # 10
print(triple(5)) # 15
# Útil para pipelines de transformación
operaciones = [lambda x: x + 1, lambda x: x * 2, lambda x: x - 3]
valor = 5
for op in operaciones:
valor = op(valor)
print(valor) # (5+1)*2-3 = 9
El bug clásico: captura de variables en bucles
# MAL: todas las lambdas capturan la MISMA variable i funciones = [lambda x: x + i for i in range(5)] print(funciones[0](10)) # 14, no 10! (i vale 4 al final del bucle) print(funciones[2](10)) # 14 # BIEN: captura el valor en el momento de creación funciones = [lambda x, i=i: x + i for i in range(5)] print(funciones[0](10)) # 10 print(funciones[2](10)) # 12
Cuándo usar def en lugar de lambda
# MAL: lambda demasiado compleja
procesador = lambda datos: [x.strip().lower() for x in datos if x.strip()]
# BIEN: def con nombre descriptivo
def normalizar_entradas(datos):
"""Limpia y normaliza una lista de cadenas."""
return [x.strip().lower() for x in datos if x.strip()]
Usa lambda cuando la función es trivial y se usa una sola vez como argumento. En cuanto la lógica necesite comentario, nombre descriptivo o más de una expresión, define una función normal con def.
