Python no es un lenguaje funcional puro, pero incorpora herramientas que permiten escribir código siguiendo este paradigma. Tres de las más conocidas son map(), filter() y reduce(), funciones de orden superior que reciben otras funciones como argumento y permiten transformar, seleccionar y combinar datos sin necesidad de bucles explícitos.
¿Qué es la programación funcional?
La programación funcional es un paradigma que trata la computación como la evaluación de funciones matemáticas, evitando el cambio de estado y los datos mutables. Sus principios clave incluyen:
- Funciones puras: dado el mismo input, siempre devuelven el mismo output, sin efectos secundarios.
- Inmutabilidad: los datos no se modifican, se generan nuevas versiones.
- Funciones como ciudadanos de primera clase: pueden pasarse como argumentos, devolverse y almacenarse en variables.
map(): transformar elementos
map() aplica una función a cada elemento de un iterable y devuelve un nuevo iterador con los resultados. Su sintaxis es:
map(funcion, iterable)Ejemplo básico
numeros = [1, 2, 3, 4, 5]
cuadrados = map(lambda x: x ** 2, numeros)
print(list(cuadrados))
# [1, 4, 9, 16, 25]map() con múltiples iterables
map() puede recibir varios iterables a la vez; la función pasada debe aceptar tantos argumentos como iterables se proporcionen.
precios = [10, 20, 30]
cantidades = [2, 3, 1]
totales = map(lambda p, c: p * c, precios, cantidades)
print(list(totales))
# [20, 60, 30]filter(): seleccionar elementos
filter() construye un iterador con los elementos de un iterable para los que una función devuelve un valor verdadero. Su sintaxis es:
filter(funcion, iterable)Ejemplo básico
numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pares = filter(lambda x: x % 2 == 0, numeros)
print(list(pares))
# [2, 4, 6, 8, 10]filter() con None
Si se pasa None como función, filter() elimina los elementos falsy (0, "", None, False, etc.).
valores = [0, 1, "", "hola", None, True, False, 42]
limpios = filter(None, valores)
print(list(limpios))
# [1, 'hola', True, 42]reduce(): combinar elementos
A diferencia de map() y filter(), reduce() no está disponible directamente; debe importarse del módulo functools. Aplica una función de dos argumentos acumulativamente a los elementos de un iterable, reduciéndolo a un único valor.
from functools import reduce
reduce(funcion, iterable[, valor_inicial])Ejemplo básico
from functools import reduce
numeros = [1, 2, 3, 4, 5]
suma = reduce(lambda acc, x: acc + x, numeros)
print(suma)
# 15reduce() con valor inicial
from functools import reduce
numeros = [1, 2, 3, 4]
producto = reduce(lambda acc, x: acc * x, numeros, 10)
print(producto)
# 240 (10 * 1 * 2 * 3 * 4)Encontrar el máximo con reduce()
from functools import reduce
numeros = [3, 7, 2, 9, 4]
maximo = reduce(lambda a, b: a if a > b else b, numeros)
print(maximo)
# 9Combinando las tres funciones
Es común encadenar map(), filter() y reduce() para construir pipelines de procesamiento de datos en una sola expresión.
from functools import reduce
numeros = range(1, 21)
resultado = reduce(
lambda acc, x: acc + x,
filter(lambda x: x % 2 == 0,
map(lambda x: x ** 2, numeros))
)
print(resultado)
# Suma de los cuadrados de los números pares del 1 al 20map/filter/reduce vs. comprensiones de listas
En Python, muchas veces las comprensiones de listas son más legibles y "pythónicas" que map() y filter():
# Con map y filter
resultado = list(filter(lambda x: x % 2 == 0, map(lambda x: x ** 2, numeros)))
# Con comprensión de listas (equivalente)
resultado = [x ** 2 for x in numeros if (x ** 2) % 2 == 0]Sin embargo, map() y filter() siguen siendo útiles cuando:
- Ya se tiene una función definida y reutilizable (no una lambda ad hoc).
- Se trabaja con iteradores perezosos y se quiere evitar crear listas intermedias en memoria.
- Se prioriza un estilo explícitamente funcional, por ejemplo combinando con
itertools.
Para reduce() no existe un equivalente directo con comprensiones, por lo que sigue siendo la herramienta natural para acumular un resultado a partir de una secuencia.
Rendimiento y evaluación perezosa (lazy evaluation)
Tanto map() como filter() devuelven iteradores, no listas. Esto significa que los valores se calculan bajo demanda, lo cual ahorra memoria al trabajar con grandes volúmenes de datos.
numeros = range(1_000_000)
cuadrados = map(lambda x: x ** 2, numeros) # No calcula nada todavía
print(next(cuadrados)) # Calcula solo el primer elemento: 0Buenas prácticas
- Usa funciones con nombre en lugar de
lambdacuando la lógica sea compleja o se reutilice. - Prefiere comprensiones de listas cuando mejoren la legibilidad.
- Aprovecha
map()yfilter()para procesar flujos de datos grandes sin cargarlos todos en memoria. - Documenta bien las funciones acumuladoras pasadas a
reduce(), ya que su lógica puede no ser evidente a simple vista.
Conclusión
map(), filter() y reduce() son herramientas fundamentales para aplicar un estilo de programación funcional en Python. Permiten transformar, seleccionar y combinar datos de forma declarativa, reduciendo la necesidad de bucles explícitos y favoreciendo un código más conciso. Aunque en muchos casos las comprensiones de listas ofrecen una alternativa más legible, comprender estas tres funciones amplía las posibilidades a la hora de diseñar soluciones, especialmente cuando se trabaja con iteradores, datos masivos o se busca un estilo explícitamente funcional.
No hay comentarios todavía. Sé el primero en compartir tu opinión.