map(), filter() y reduce() en Python: funciones de orden superior
Esta lección es una traducción del original en inglés.Read in EnglishAvisar de un error de traducción
Imagina una cadena de montaje en una fábrica. Las materias primas entran por un extremo. En la primera estación se da forma a cada pieza. En la siguiente se retiran las piezas defectuosas. En la estación final, todas las piezas buenas se combinan en un único producto terminado.
Python tiene tres funciones que trabajan exactamente como esta cadena de montaje: map() transforma cada elemento, filter() se queda solo con los elementos que quieres y reduce() lo combina todo en un único resultado. Juntas, te permiten procesar colecciones de datos de forma limpia y legible.
En este tutorial aprenderás cómo funcionan estas herramientas, cuándo usarlas y cuándo una comprensión de listas (list comprehension) puede ser mejor opción. Al terminar, escribirás pipelines de datos que harían sentir orgulloso a cualquier jefe de fábrica.
¿Qué son las funciones de orden superior?
Una función de orden superior es una función que recibe otra función como argumento o que devuelve una función como resultado. Eso es todo.
Ya has usado una sin darte cuenta. La función integrada sorted() tiene un parámetro key al que le pasas una función:
['apple', 'banana', 'cherry']
Aquí, len se pasa como argumento a sorted(). La función sorted llama a len con cada elemento para decidir el orden. Tú no llamaste a len(): solo le dijiste a sorted qué función usar.
map(), filter() y reduce() funcionan todas así. Les das una función y una colección, y ellas aplican esa función a los elementos. Eso es lo que las convierte en funciones de orden superior.
map(): transforma cada elemento
map() recibe una función y un iterable (como una lista), aplica la función a cada elemento y devuelve los resultados transformados. Piensa en ella como la "estación de moldeado" de nuestra cadena de montaje.
La sintaxis es: map(function, iterable). Devuelve un objeto map, que normalmente conviertes en lista.
[2, 4, 6, 8, 10]
map(double, numbers) llama a double(1), double(2), double(3), etc., y reúne todos los resultados. La llamada a list() que lo envuelve convierte el objeto map en una lista normal para que podamos imprimirla.
Como escribir una función entera solo para duplicar un número resulta pesado, map() se suele combinar con una lambda, una función anónima diminuta:
[2, 4, 6, 8, 10] ['ALICE', 'BOB', 'CHARLIE'] [10, 20, 6]
Puedes pasar cualquier función a map(): tus propias funciones, lambdas o funciones integradas como str.upper, round, len o int.
filter(): quédate solo con lo que necesitas
filter() recibe una función y un iterable. La función debe devolver True o False para cada elemento. Solo se conservan los elementos para los que la función devuelve True. Piensa en ella como el control de calidad de la cadena de montaje: se retiran las piezas defectuosas.
[2, 4, 6, 8, 10]
filter(is_even, numbers) llama a is_even(1), que devuelve False (así que el 1 se descarta), a is_even(2), que devuelve True (así que el 2 se conserva), y así sucesivamente. Solo sobreviven los elementos que pasan la prueba.
['hello', 'world', 'python'] ['hello', 'world', 'python'] [2, 5, 8]
Pasar bool a filter() es un truco muy práctico. Las cadenas vacías, el cero, None y las listas vacías son valores "falsy" en Python (se evalúan como falsos): bool() devuelve False para ellos. Así que filter(bool, items) elimina todos los valores falsy.
Combinar map() y filter()
La verdadera potencia aparece al encadenarlas. Primero filtras para seleccionar elementos y luego aplicas map para transformarlos, igual que las estaciones de una cadena de montaje.
[87, 96, 72, 78, 93, 100, 65]
Como tanto filter() como map() son perezosas, puedes encadenarlas sin crear listas intermedias. Los datos fluyen por el pipeline de forma eficiente.
Aquí tienes un ejemplo más práctico, que procesa una lista de precios de productos:
[10.39, 71.99, 36.0, 120.0]
reduce(): combina todos los elementos en uno
reduce() recibe una función y un iterable, y combina todos los elementos en un único valor. Es la estación final de la cadena de montaje: todas las piezas se ensamblan en un solo producto.
A diferencia de map() y filter(), reduce() no es una función integrada. Tienes que importarla del módulo functools.
Sum: 15 Product: 120
Así funciona reduce() paso a paso en la suma. La función recibe dos argumentos: el resultado acumulado hasta el momento (a) y el siguiente elemento (b):
a=1, b=2 da 3a=3, b=3 da 6a=6, b=4 da 10a=10, b=5 da 15Longest word: hippopotamus Alice & Bob & Charlie
map/filter frente a comprensiones de listas
Python ofrece otra forma de transformar y filtrar listas: las comprensiones de listas. A menudo dan un código más legible que map() y filter(). Comparemos.
numbers = [1, 2, 3, 4, 5, 6]
# Double even numbers
evens = filter(lambda x: x % 2 == 0, numbers)
result = list(map(lambda x: x * 2, evens))
print(result) # [4, 8, 12]numbers = [1, 2, 3, 4, 5, 6]
# Double even numbers
result = [x * 2 for x in numbers if x % 2 == 0]
print(result) # [4, 8, 12]La comprensión de listas filtra y transforma en una sola línea fácil de leer. Para transformaciones sencillas, las comprensiones suelen ser la mejor opción en Python.
Entonces, ¿cuándo conviene usar map() y filter()? Son útiles cuando ya tienes una función con nombre que aplicar:
['Alice', 'Bob', 'Charlie'] ['Alice', 'Bob', 'Charlie']
Ejercicios de práctica
Es hora de practicar. Estos ejercicios empiezan con funciones sueltas y avanzan hasta combinarlas en pipelines. Recuerda envolver map() y filter() en list() al imprimir.
Usa map() con una lambda para elevar al cuadrado cada número de la lista [1, 2, 3, 4, 5].
Imprime el resultado como lista.
Salida esperada:
[1, 4, 9, 16, 25]Usa filter() con una lambda para quedarte solo con las palabras que tienen más de 3 caracteres.
Datos: ["hi", "hello", "hey", "world", "ok", "python"]
Imprime el resultado como lista.
Salida esperada:
['hello', 'world', 'python']Lee este código y predice la salida. Después escribe una instrucción print() que produzca exactamente la misma salida.
numbers = [10, 25, 30, 45, 50]
result = list(map(lambda x: x // 10, filter(lambda x: x >= 30, numbers)))
print(result)Piensa paso a paso: ¿qué conserva filter y qué hace después map con cada elemento?
Este código debería convertir una lista de temperaturas en texto, como ["32F", "100F", "212F"], en enteros en grados Celsius. Pero tiene dos errores.
Salida esperada:
[0, 38, 100]Fórmula: Celsius = (Fahrenheit - 32) * 5 / 9, y luego se redondea al entero más cercano.
Usa reduce() del módulo functools para calcular el producto de todos los números de la lista [2, 3, 4, 5].
El producto es 2 * 3 * 4 * 5 = 120.
Imprime el resultado.
Salida esperada:
120Dada una lista de calificaciones de estudiantes, construye un pipeline que:
1. Descarte las calificaciones que no aprueban (conserva solo las calificaciones >= 60)
2. Suba cada calificación aprobada sumándole 10 (usa map)
3. Limite las calificaciones a un máximo de 100 (usa map con min)
Datos: [45, 82, 55, 91, 67, 38, 73, 95]
Imprime la lista final.
Salida esperada:
[92, 100, 77, 83, 100]Pista: para limitar a 100, usa min(score, 100).
Reescribe este pipeline de map/filter como una sola comprensión de listas que produzca la misma salida.
Código original:
words = ["Hello", "WORLD", "Python", "CODE", "test"]
result = list(map(str.lower, filter(lambda w: len(w) > 4, words)))Escribe una comprensión de listas que produzca el mismo resultado e imprímelo.
Salida esperada:
['hello', 'world', 'python']Resumen
Lo que ya sabes sobre las herramientas funcionales de Python:
| Función | Para qué sirve | Devuelve |
|---|---|---|
map(fn, iterable) | Transforma cada elemento | Objeto map (perezoso) |
filter(fn, iterable) | Conserva los elementos para los que fn devuelve True | Objeto filter (perezoso) |
reduce(fn, iterable) | Combina todos los elementos en un solo valor | Un único valor |
| Función de orden superior | Una función que recibe o devuelve una función | Depende de la función |
La conclusión práctica: usa comprensiones de listas para la mayoría de las tareas de transformar o filtrar en Python. Recurre a map() y filter() cuando tengas una función con nombre que aplicar o necesites evaluación perezosa. Usa reduce() con moderación: las funciones integradas de Python resuelven mejor la mayoría de los casos.
¿Qué sigue?
Ya tienes una base sólida en funciones de Python. Ahora explora el [manejo de errores](/python/python-try-except) para aprender a escribir código que gestione los fallos con elegancia en lugar de detenerse con un error.