Funciones Lambda en Python: Una guía clara con ejemplos prácticos
Updated on
Todo proyecto Python acumula pequeñas funciones auxiliares. Una función que duplica un número. Otra que elimina espacios en blanco. Una más que extrae un apellido de un diccionario. Cada una tiene dos o tres líneas, se usa exactamente una vez y llena el módulo con nombres que nunca recordarás. Las funciones lambda de Python resuelven este problema permitiéndote definir funciones pequeñas y desechables justo donde las necesitas -- sin def, sin nombre, sin espacio vertical desperdiciado.
Esta guía cubre todo lo que necesitas saber sobre las funciones lambda de Python: la sintaxis, las funciones integradas con las que se combinan, patrones prácticos para código del mundo real y las situaciones específicas en las que deberías evitarlas.
¿Qué es una función Lambda?
Una función lambda es una función anónima de expresión única. "Anónima" significa que no tiene nombre. "Expresión única" significa que el cuerpo de la función es exactamente una expresión cuyo resultado se devuelve automáticamente. Python evalúa esa expresión y devuelve el resultado -- no se necesita una instrucción return.
El término proviene del cálculo lambda, un sistema formal en la lógica matemática. Pero no necesitas entender las matemáticas. En Python práctico, un lambda es simplemente una forma más corta de escribir una función pequeña.
Aquí hay una función regular y su equivalente lambda:
# Regular function
def double(x):
return x * 2
print(double(5))
# 10
# Lambda equivalent
double_lambda = lambda x: x * 2
print(double_lambda(5))
# 10Ambas producen el mismo resultado. La versión lambda cabe en una línea y omite la ceremonia de def y return.
Sintaxis Lambda
La sintaxis para un lambda en Python es:
lambda arguments: expressionlambda-- la palabra clave que señala una función anónima.arguments-- cero o más parámetros, separados por comas. No se requieren paréntesis.expression-- una expresión única que se evalúa y devuelve. Sin instrucciones (sin bloquesif, sin buclesfor, sin asignaciones con=).
Algunos ejemplos rápidos para mostrar el rango:
# No arguments
greet = lambda: "Hello, world!"
print(greet())
# Hello, world!
# One argument
square = lambda x: x ** 2
print(square(9))
# 81
# Two arguments
add = lambda a, b: a + b
print(add(3, 7))
# 10
# Default argument
power = lambda base, exp=2: base ** exp
print(power(3))
# 9
print(power(3, 3))
# 27La restricción clave es que el cuerpo debe ser una expresión única. No puedes escribir lógica multilínea, usar instrucciones if (aunque puedes usar expresiones condicionales), ni incluir asignaciones. Esto es intencional -- los lambdas están diseñados para operaciones simples.
Lambda con map() -- Transformar listas
map() aplica una función a cada elemento de un iterable y devuelve un iterador. Las funciones lambda son el compañero natural de map() porque la transformación es a menudo lo suficientemente simple como para expresarse en una línea.
numbers = [1, 2, 3, 4, 5]
# Square each number
squared = list(map(lambda x: x ** 2, numbers))
print(squared)
# [1, 4, 9, 16, 25]
# Convert temperatures from Celsius to Fahrenheit
celsius = [0, 20, 37, 100]
fahrenheit = list(map(lambda c: round(c * 9/5 + 32, 1), celsius))
print(fahrenheit)
# [32.0, 68.0, 98.6, 212.0]
# Extract first names from full names
names = ["Ada Lovelace", "Grace Hopper", "Alan Turing"]
first_names = list(map(lambda name: name.split()[0], names))
print(first_names)
# ['Ada', 'Grace', 'Alan']map() con un lambda es una alternativa limpia a una comprensión de lista cuando la lógica de mapeo es una transformación directa de un solo paso. Para transformaciones más complejas, las comprensiones de lista tienden a ser más legibles.
Lambda con filter() -- Filtrar elementos
filter() toma una función y un iterable, y devuelve un iterador que produce solo los elementos para los cuales la función devuelve True. Las funciones lambda facilitan definir el predicado en línea.
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Keep only even numbers
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)
# [2, 4, 6, 8, 10]
# Keep strings longer than 4 characters
words = ["cat", "elephant", "dog", "butterfly", "ant"]
long_words = list(filter(lambda w: len(w) > 4, words))
print(long_words)
# ['elephant', 'butterfly']
# Filter out None values
data = [1, None, 3, None, 5, None, 7]
clean = list(filter(lambda x: x is not None, data))
print(clean)
# [1, 3, 5, 7]Al igual que map(), la combinación de filter() + lambda funciona mejor para condiciones simples. Si la lógica de filtrado involucra múltiples comprobaciones, una comprensión de lista o una función con nombre suele ser más clara.
Lambda con sorted() y sort() -- Claves de ordenación personalizadas
La ordenación es uno de los usos más comunes y prácticos de las funciones lambda. La función sorted() y el método .sort() aceptan un parámetro key -- una función que extrae un valor de comparación de cada elemento.
# Sort strings by length
fruits = ["banana", "kiwi", "strawberry", "fig", "apple"]
by_length = sorted(fruits, key=lambda s: len(s))
print(by_length)
# ['fig', 'kiwi', 'apple', 'banana', 'strawberry']
# Sort tuples by the second element
pairs = [(1, 'b'), (3, 'a'), (2, 'c')]
by_second = sorted(pairs, key=lambda pair: pair[1])
print(by_second)
# [(3, 'a'), (1, 'b'), (2, 'c')]
# Sort dictionaries by a specific key
students = [
{"name": "Alice", "grade": 88},
{"name": "Bob", "grade": 95},
{"name": "Charlie", "grade": 72},
]
by_grade = sorted(students, key=lambda s: s["grade"], reverse=True)
for s in by_grade:
print(f"{s['name']}: {s['grade']}")
# Bob: 95
# Alice: 88
# Charlie: 72La ordenación con lambda es tan ampliamente utilizada que se ha convertido en un patrón idiomático de Python. Cada vez que necesites ordenar objetos complejos por un atributo o campo específico, una función key lambda es el enfoque estándar.
Ordenación con múltiples criterios
Puedes devolver una tupla desde el lambda para ordenar por múltiples campos:
employees = [
{"name": "Alice", "dept": "Engineering", "salary": 95000},
{"name": "Bob", "dept": "Marketing", "salary": 72000},
{"name": "Charlie", "dept": "Engineering", "salary": 88000},
{"name": "Diana", "dept": "Marketing", "salary": 85000},
]
# Sort by department (ascending), then by salary (descending)
sorted_emp = sorted(employees, key=lambda e: (e["dept"], -e["salary"]))
for e in sorted_emp:
print(f"{e['dept']:12s} {e['name']:8s} ${e['salary']:,}")
# Engineering Alice $95,000
# Engineering Charlie $88,000
# Marketing Diana $85,000
# Marketing Bob $72,000Lambda con reduce() de functools
functools.reduce() aplica una función de dos argumentos de forma acumulativa a los elementos de un iterable, reduciéndolo a un solo valor. Las funciones lambda se combinan naturalmente con reduce() para agregaciones concisas.
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# Product of all numbers
product = reduce(lambda x, y: x * y, numbers)
print(product)
# 120
# Find the maximum value (for demonstration; use max() in practice)
largest = reduce(lambda a, b: a if a > b else b, numbers)
print(largest)
# 5
# Concatenate a list of strings
words = ["Python", " ", "lambda", " ", "functions"]
sentence = reduce(lambda a, b: a + b, words)
print(sentence)
# Python lambda functions
# Flatten a list of lists
nested = [[1, 2], [3, 4], [5, 6]]
flat = reduce(lambda acc, lst: acc + lst, nested)
print(flat)
# [1, 2, 3, 4, 5, 6]Una advertencia: reduce() puede oscurecer la intención. Para operaciones comunes como sumar, usa sum(). Para encontrar mín/máx, usa min() y max(). Reserva reduce() con lambda para acumulaciones personalizadas donde no existe una función integrada.
Lambda vs def -- Cuándo usar cada uno
Esta es la pregunta que más importa en la práctica. Lambda y def crean objetos función, pero sirven para propósitos diferentes.
| Característica | lambda | def |
|---|---|---|
| Nombre | Anónimo (sin nombre) | Función con nombre |
| Cuerpo | Solo expresión única | Múltiples instrucciones, bucles, condiciones |
| Retorno | Implícito (resultado de expresión) | Instrucción return explícita |
| Docstrings | No soportado | Soportado |
| Type hints | No soportado | Soportado |
| Depuración | Muestra <lambda> en trazas | Muestra nombre de función en trazas |
| Legibilidad | Mejor para operaciones simples y cortas | Mejor para cualquier cosa multi-paso |
| Testabilidad | Más difícil de probar aisladamente | Fácil de probar por nombre |
| Reutilización | Típicamente uso único, en línea | Diseñado para reutilización |
| Decoradores | No puede usar sintaxis @decorator | Soporte completo de decoradores |
Cuándo usar Lambda
- Claves de ordenación:
sorted(items, key=lambda x: x.name) - Operaciones rápidas de map/filter:
map(lambda x: x.strip(), lines) - Argumentos callback: funciones que aceptan un parámetro invocable
- Acceso simple a diccionario o tupla:
key=lambda item: item[1]
Cuándo usar def
- La función tiene más de una expresión
- Necesitas un docstring o type hints
- La función será llamada desde múltiples lugares
- La lógica requiere manejo de errores o ramificación
- Necesitas un nombre significativo en las trazas de pila para depuración
Regla general: si el lambda no cabe cómodamente en una sola línea, o si necesitas leerlo dos veces para entender lo que hace, usa def en su lugar.
Lambda con múltiples argumentos
Las funciones lambda pueden aceptar cualquier número de argumentos, incluyendo *args y **kwargs:
# Three arguments
volume = lambda l, w, h: l * w * h
print(volume(3, 4, 5))
# 60
# Using *args for variable arguments
sum_all = lambda *args: sum(args)
print(sum_all(1, 2, 3, 4, 5))
# 15
# Using **kwargs
build_greeting = lambda **kwargs: f"Hello, {kwargs.get('name', 'stranger')}!"
print(build_greeting(name="Alice"))
# Hello, Alice!
print(build_greeting())
# Hello, stranger!
# Conditional expression inside lambda
classify = lambda x: "positive" if x > 0 else ("zero" if x == 0 else "negative")
print(classify(5))
# positive
print(classify(0))
# zero
print(classify(-3))
# negativeObserva la expresión condicional (a if condition else b) en el último ejemplo. Esta es la única forma de agregar lógica de ramificación dentro de un lambda. Funciona, pero anidar múltiples condiciones reduce la legibilidad rápidamente.
Lambda en operaciones con diccionarios
Las funciones lambda son útiles para transformar y ordenar datos de diccionarios:
# Sort a dictionary by value
scores = {"Alice": 88, "Bob": 95, "Charlie": 72, "Diana": 91}
sorted_scores = dict(sorted(scores.items(), key=lambda item: item[1], reverse=True))
print(sorted_scores)
# {'Bob': 95, 'Diana': 91, 'Alice': 88, 'Charlie': 72}
# Apply a transformation to all dictionary values
prices = {"apple": 1.20, "banana": 0.50, "cherry": 2.00}
discounted = {k: round(v * 0.9, 2) for k, v in prices.items()}
print(discounted)
# {'apple': 1.08, 'banana': 0.45, 'cherry': 1.8}
# Group items using a lambda as a key function
from itertools import groupby
data = ["apple", "avocado", "banana", "blueberry", "cherry", "cranberry"]
data_sorted = sorted(data, key=lambda x: x[0])
for letter, group in groupby(data_sorted, key=lambda x: x[0]):
print(f"{letter}: {list(group)}")
# a: ['apple', 'avocado']
# b: ['banana', 'blueberry']
# c: ['cherry', 'cranberry']Lambda con Pandas: df.apply() y df.sort_values()
Las funciones lambda se usan intensamente en pandas para transformaciones a nivel de fila y ordenación personalizada. El método apply() ejecuta una función en cada fila o columna de un DataFrame, y lambda mantiene el código en línea.
import pandas as pd
df = pd.DataFrame({
"name": ["Alice", "Bob", "Charlie", "Diana"],
"score": [88, 95, 72, 91],
"department": ["Engineering", "Marketing", "Engineering", "Marketing"]
})
# Add a new column with a grade label
df["grade"] = df["score"].apply(lambda x: "A" if x >= 90 else ("B" if x >= 80 else "C"))
print(df)
# name score department grade
# 0 Alice 88 Engineering B
# 1 Bob 95 Marketing A
# 2 Charlie 72 Engineering C
# 3 Diana 91 Marketing AUsando Lambda con sort_values(key=)
El parámetro key en sort_values() acepta una función aplicada a la columna antes de ordenar:
import pandas as pd
df = pd.DataFrame({
"product": ["Widget A", "Widget B", "Widget C"],
"price": ["$29.99", "$9.50", "$149.00"]
})
# Sort by numeric price value (strip the $ sign first)
df_sorted = df.sort_values("price", key=lambda col: col.str.replace("$", "", regex=False).astype(float))
print(df_sorted)
# product price
# 1 Widget B $9.50
# 0 Widget A $29.99
# 2 Widget C $149.00Usando Lambda con apply() a través de filas
Establece axis=1 para aplicar un lambda a cada fila:
import pandas as pd
df = pd.DataFrame({
"first_name": ["Ada", "Grace", "Alan"],
"last_name": ["Lovelace", "Hopper", "Turing"],
"birth_year": [1815, 1906, 1912]
})
# Create a full name column
df["full_name"] = df.apply(lambda row: f"{row['first_name']} {row['last_name']}", axis=1)
# Calculate age (approximate, as of 2026)
df["approx_age"] = df["birth_year"].apply(lambda y: 2026 - y)
print(df)
# first_name last_name birth_year full_name approx_age
# 0 Ada Lovelace 1815 Ada Lovelace 211
# 1 Grace Hopper 1906 Grace Hopper 120
# 2 Alan Turing 1912 Alan Turing 114Patrones y modismos comunes de Lambda
Aquí hay patrones que encontrarás frecuentemente en código Python de producción:
# 1. Default factory for collections.defaultdict
from collections import defaultdict
word_count = defaultdict(lambda: 0)
for word in ["apple", "banana", "apple", "cherry", "banana", "apple"]:
word_count[word] += 1
print(dict(word_count))
# {'apple': 3, 'banana': 2, 'cherry': 1}
# 2. Immediate invocation (IIFE - Immediately Invoked Function Expression)
result = (lambda x, y: x + y)(3, 4)
print(result)
# 7
# 3. Lambda as a callback in GUI or event-driven code
# button.on_click(lambda event: print(f"Clicked at {event.x}, {event.y}"))
# 4. Using lambda with min/max for custom comparisons
products = [
("Laptop", 999),
("Mouse", 25),
("Keyboard", 75),
("Monitor", 450),
]
cheapest = min(products, key=lambda p: p[1])
print(cheapest)
# ('Mouse', 25)
# 5. Lambda with conditional expression for data cleaning
clean = lambda s: s.strip().lower() if isinstance(s, str) else s
print(clean(" Hello World "))
# hello world
print(clean(42))
# 42Cuándo NO usar Lambda
Las funciones lambda tienen límites claros. Usarlas más allá de esos límites lleva a código que es más difícil de leer, depurar y mantener.
Evita lambda cuando:
- La lógica es compleja. Si necesitas condiciones anidadas, múltiples operaciones o cualquier forma de manejo de errores, usa
def.
# Bad -- hard to read
process = lambda x: x.strip().lower().replace(" ", "_") if isinstance(x, str) and len(x) > 0 else "empty"
# Good -- clear and testable
def process(x):
"""Normalize a string to a snake_case identifier."""
if not isinstance(x, str) or len(x) == 0:
return "empty"
return x.strip().lower().replace(" ", "_")
print(process(" Hello World "))
# hello_world-
Asignas el lambda a una variable para reutilización. PEP 8 recomienda explícitamente usar
defen lugar de asignar un lambda a un nombre. Si la función merece un nombre, dale una definición apropiada. -
Necesitas un docstring o type hints. Las funciones lambda no soportan ninguno de los dos. Las funciones con nombre sí.
-
La depuración importa. Las funciones lambda aparecen como
<lambda>en las trazas, lo que hace difícil identificar cuál lambda causó un error cuando tienes varias. -
La legibilidad sufre. Si un colega necesita más de tres segundos para entender tu lambda, reescríbelo como una función con nombre.
| Situación | Usar lambda | Usar def |
|---|---|---|
Clave de ordenación para sorted() | Sí | Solo si es complejo |
map()/filter() rápido | Sí | Si es multi-paso |
| Reutilizado en múltiples lugares | No | Sí |
| Ramificación compleja | No | Sí |
| Necesita un docstring | No | Sí |
| Callback en API | Sí | Si la lógica crece |
| Se necesita manejo de errores | No | Sí |
Escribir y refactorizar funciones Lambda con RunCell
Trabajar con funciones lambda en notebooks Jupyter es común en flujos de trabajo de ciencia de datos. Cuando estás escribiendo llamadas complejas a pandas apply() o encadenando múltiples operaciones map() y filter(), puede ser difícil saber si un lambda es la herramienta correcta o si deberías refactorizar a una función con nombre.
RunCell (opens in a new tab) es un agente de IA diseñado para trabajar directamente dentro de notebooks Jupyter. Entiende el contexto de tu notebook -- las variables en memoria, los DataFrames con los que trabajas, los imports que has cargado -- y da sugerencias dirigidas.
Así es como RunCell ayuda específicamente con funciones lambda:
- Refactorización de lambda a def. Cuando un lambda crece demasiado, RunCell puede sugerir una versión limpia con
def, type hints y un docstring, preservando el comportamiento exacto. - Sugerencias de rendimiento. Si estás usando
df.apply(lambda ...)en un DataFrame grande, RunCell puede sugerir alternativas vectorizadas usando operaciones nativas de pandas o NumPy que son 10-100x más rápidas. - Explicaciones en línea. ¿Trabajando con código ajeno lleno de lambdas anidados? RunCell puede desglosar lo que hace cada lambda en lenguaje simple, directamente en el notebook.
- Sugerencias de patrones. Describe lo que quieres -- "ordena esta lista de dicts por fecha, luego por nombre" -- y RunCell genera la llamada correcta a
sorted()con la función key lambda adecuada.
Como RunCell se ejecuta dentro de tu entorno Jupyter existente, no hay cambio de contexto. Te quedas en el notebook y el agente de IA trabaja junto a ti.
FAQ
¿Qué es una función lambda en Python?
Una función lambda es una función pequeña y anónima definida con la palabra clave lambda. Puede tomar cualquier número de argumentos pero solo puede contener una expresión única. El resultado de la expresión se devuelve automáticamente. Las funciones lambda se usan típicamente para operaciones cortas y desechables como claves de ordenación, callbacks de map/filter y transformaciones en línea.
¿Puede un lambda de Python tener múltiples líneas?
No. Un lambda de Python está restringido a una expresión única. No puedes usar múltiples instrucciones, bucles o asignaciones en un lambda. Si necesitas lógica multilínea, usa una función def regular. Sin embargo, puedes usar una expresión condicional (a if condition else b) dentro de un lambda para ramificación simple.
¿Cuál es la diferencia entre lambda y def en Python?
Ambos crean objetos función, pero difieren en alcance: lambda crea funciones anónimas de expresión única usadas en línea, mientras que def crea funciones con nombre que pueden contener múltiples instrucciones, docstrings, type hints y decoradores. Usa lambda para operaciones simples de un solo uso; usa def para cualquier cosa que necesite un nombre, documentación o lógica compleja.
¿Cuándo debería usar lambda en lugar de una comprensión de lista?
Usa lambda con map() o filter() cuando la operación es una transformación o predicado simple y único. Usa comprensiones de lista cuando necesites tanto filtrado como transformación en un solo paso, o cuando la lógica se beneficie de la estructura [expr for x in iterable if condition]. En Python moderno, las comprensiones de lista generalmente se prefieren por legibilidad, pero lambda es estándar para claves de ordenación y parámetros callback.
¿Son lentas las funciones lambda de Python?
No. Las funciones lambda tienen el mismo rendimiento que las funciones def equivalentes. La sobrecarga de llamar a cualquiera de las dos es idéntica. Sin embargo, usar df.apply(lambda ...) en pandas es lento comparado con operaciones vectorizadas. El cuello de botella es la ejecución fila por fila de Python, no el lambda en sí. Siempre que sea posible, reemplaza apply(lambda ...) con métodos integrados de pandas o NumPy para mejor rendimiento.
Conclusión
Las funciones lambda de Python llenan un nicho específico: funciones cortas y anónimas que defines exactamente donde las necesitas. Son mejores como claves de ordenación, callbacks de map()/filter() y transformaciones en línea. Se combinan naturalmente con sorted(), map(), filter(), reduce() y pandas apply().
Las reglas para usarlas bien son directas:
- Mantenlas en una expresión simple.
- Úsalas en línea, no asignadas a variables (directriz PEP 8).
- Cambia a
defen el momento en que la lógica se vuelva difícil de leer. - En pandas, prefiere operaciones vectorizadas sobre
apply(lambda ...)para rendimiento. - Usa expresiones condicionales con moderación -- ternarios anidados en un lambda son una trampa de legibilidad.
Lambda es una herramienta, no una insignia de inteligencia. El mejor código Python usa lambda donde simplifica y def donde clarifica. Conocer el límite entre los dos es lo que separa el código legible del código que hace que tu yo futuro (o tus compañeros de equipo) luchen.