Pregunta 1¿Qué imprime este código?nums = [1, 2, 3]
print(list(map(lambda x: x + 10, nums)))
map() — Aplicar una función a cada elemento de una lista de golpe
Aprende la función integrada map() de Python para aplicar una función a cada elemento de un iterable de golpe.
En el artículo anterior sobre decoradores viste cómo envolver comportamiento extra alrededor de una función. Esta vez cambiarás de marcha y mirarás la función integrada map() — la herramienta a la que recurres cuando quieres aplicar la misma función a cada elemento de una lista de golpe.
map() se empareja de forma natural con las lambdas, y el mecanismo subyacente es similar a una comprensión de lista. Hoy en día, las comprensiones suelen ser la elección recomendada frente a map().
Qué es map() — Una función de orden superior que llega a cada elemento
map(función, iterable) aplica la función del primer argumento a cada elemento del segundo argumento (una lista, tupla, etc.) y retorna un objeto map que te permite extraer los resultados uno a uno. Puedes iterarlo con for, o envolverlo en list() para materializar todo como una lista.
Como su primer argumento es una función, map() cuenta como una función de orden superior.
map. Envuélvelo en list() para materializar el contenido.numbers = [1, 2, 3, 4, 5]
squared = map(lambda x: x ** 2, numbers)
print(type(squared)) # <class 'map'>
print(squared) # <map object at 0x...>
# Extrae valores con list()
print(list(squared)) # [1, 4, 9, 16, 25]
# Las funciones integradas también funcionan (convierte una lista de cadenas a int)
str_nums = ["10", "20", "30"]
print(list(map(int, str_nums))) # [10, 20, 30]
Un objeto map es de un solo uso
El valor de retorno de map() es un iterador — del mismo tipo que obtienes de un generador — y una vez que lo has recorrido, está vacío. Llama a list(squared) por segunda vez y obtendrás []. Si necesitas usar los resultados más de una vez, haz list(map(...)) por adelantado y trabaja con la lista.
Pasar varios iterables a la vez
Desde el segundo argumento en adelante, map() acepta varios iterables. En ese caso, la función del primer argumento necesita aceptar un elemento de cada uno en la posición correspondiente. Escribe map(función, A, B) y la función se aplica al par A[0] y B[0], luego A[1] y B[1], y así sucesivamente.
Por ejemplo, para multiplicar dos listas numéricas elemento a elemento, map(lambda a, b: a * b, A, B) te da una lista de productos por pares.
A = [1, 2, 3]
B = [10, 20, 30]
# Multiplica elementos en el mismo índice
print(list(map(lambda a, b: a * b, A, B))) # [10, 40, 90]
# Lo mismo con tres iterables
def calculate(x, y, op):
return x + y if op == "plus" else x - y
xs = [10, 20, 30]
ys = [3, 3, 3]
ops = ["plus", "minus", "plus"]
print(list(map(calculate, xs, ys, ops))) # [13, 17, 33]
A y B en el mismo índice se emparejan y se pasan a la lambda lambda a, b: a * b.Las longitudes desiguales paran en la más corta
Cuando los iterables que pasas tienen longitudes diferentes, map() para en el más corto. Por ejemplo, map(f, [1, 2, 3, 4], [10, 20]) solo se ejecuta dos veces. Si quieres alineamiento explícito, comprueba las longitudes de antemano, o empareja map() con `zip()` según necesites.
map() vs comprensión de lista — ¿Cuál deberías usar?
Casi todo lo que map() puede hacer, una comprensión de lista también puede hacerlo. La documentación oficial de Python y libros como Fluent Python recomiendan preferir las comprensiones en código nuevo, y en el Python moderno, las comprensiones son la forma estándar.
map() solía ser la opción por defecto en código antiguo, pero su papel se ha reducido a casos donde puedes pasar un nombre de función existente sin escribir una lambda (piensa en map(int, str_nums)). Pongamos las diferencias lado a lado.
| Objetivo | Con map() | Con comprensión |
|---|---|---|
| Elevar al cuadrado cada elemento | list(map(lambda x: x ** 2, nums)) | [x ** 2 for x in nums] |
| Convertir str a int | list(map(int, str_nums)) | [int(s) for s in str_nums] |
| Dos listas a la vez | list(map(f, A, B)) | [f(a, b) for a, b in zip(A, B)] |
nums = [1, 2, 3, 4, 5]
# Versión map()
print(list(map(lambda x: x ** 2, nums))) # [1, 4, 9, 16, 25]
# Versión comprensión (preferida)
print([x ** 2 for x in nums]) # [1, 4, 9, 16, 25]
# Cuando puedes pasar un nombre de función directamente, map() se ve más limpio
str_nums = ["10", "20", "30"]
print(list(map(int, str_nums))) # [10, 20, 30]
print([int(s) for s in str_nums]) # [10, 20, 30]
# Al filtrar, las comprensiones son mucho más concisas
print([x for x in nums if x % 2 == 0]) # [2, 4]
Cuando dudes, tira de una comprensión
Tanto si quieres transformar, filtrar, o hacer ambas cosas, una comprensión te permite escribirlo todo de forma natural dentro de los mismos corchetes. Si te comprometes a usar map() solo cuando pasas un nombre de función existente tal cual, tu código se mantiene consistente. Es más ligero tanto para quien escribe como para quien lee, así que prefiere las comprensiones en código nuevo.
Verificación de conocimientos
Responde cada pregunta una a una.
Pregunta 2¿Qué comprensión produce el mismo resultado que list(map(int, ["1", "2", "3"]))?
Pregunta 3¿Qué afirmación sobre el valor de retorno de map() es correcta?