Cómo usar filtrar, mapear y reducir en Python 3
filter
, map
, y reduce
funcionan perfectamente en Python 2. He aquí un ejemplo:
>>> def f(x):
return x % 2 != 0 and x % 3 != 0
>>> filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x):
return x*x*x
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> def add(x,y):
return x+y
>>> reduce(add, range(1, 11))
55
Pero en Python 3, recibo las siguientes salidas:
>>> filter(f, range(2, 25))
<filter object at 0x0000000002C14908>
>>> map(cube, range(1, 11))
<map object at 0x0000000002C82B70>
>>> reduce(add, range(1, 11))
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
reduce(add, range(1, 11))
NameError: name 'reduce' is not defined
Agradecería que alguien me explicara por qué es esto.
Captura de pantalla del código para mayor claridad:
4 answers
Puedes leer sobre los cambios en Qué hay De Nuevo En Python 3.0. Usted debe leer a fondo cuando se mueve de 2.x a 3.x desde que mucho ha cambiado.
La respuesta completa aquí son citas de la documentación.
Vistas E Iteradores En Lugar De Listas
Algunas API bien conocidas ya no devuelven listas:
- [...]
map()
yfilter()
el retorno de los iteradores. Si realmente necesitas un list, una solución rápida es, por ejemplo,list(map(...))
, pero una mejor solución es a menudo usar una comprensión de lista (especialmente cuando el código original usa lambda), o reescribir el código para que no necesite una lista en absoluto. Particularmente difícil esmap()
invocado para los efectos secundarios de la función; la transformación correcta es utilizar un bucle regularfor
(ya que crear una lista sería un desperdicio).- [...]
- [...]
- Eliminado
reduce()
. Usofunctools.reduce()
si realmente lo necesita; sin embargo, el 99 por ciento de las veces un buclefor
explícito es más legible.- [...]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-30 04:22:03
La funcionalidad de map
y filter
se cambió intencionalmente para devolver iteradores, y reduce se eliminó de ser un built-in y se colocó en functools.reduce
.
Entonces, para filter
y map
, puedes envolverlos con list()
para ver los resultados como lo hiciste antes.
>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> list(filter(f, range(2, 25)))
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> list(map(cube, range(1, 11)))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> import functools
>>> def add(x,y): return x+y
...
>>> functools.reduce(add, range(1, 11))
55
>>>
La recomendación ahora es que reemplace su uso de mapa y filtro con expresiones generators o comprensiones de listas. Ejemplo:
>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> [i for i in range(2, 25) if f(i)]
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> [cube(i) for i in range(1, 11)]
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>>
Dicen que los bucles for son el 99 por ciento de las veces más fáciles de leer que reducir, pero me quedaría con functools.reduce
.
Editar : La cifra del 99 por ciento se extrae directamente de la página Qué hay de nuevo En Python 3.0 escrita por Guido van Rossum.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-25 06:48:31
Como un anexo a las otras respuestas, esto suena como un buen caso de uso para un administrador de contexto que reasignará los nombres de estas funciones a las que devuelven una lista e introducirán reduce
en el espacio de nombres global.
Una implementación rápida podría verse así:
from contextlib import contextmanager
@contextmanager
def noiters(*funcs):
if not funcs:
funcs = [map, filter, zip] # etc
from functools import reduce
globals()[reduce.__name__] = reduce
for func in funcs:
globals()[func.__name__] = lambda *ar, func = func, **kwar: list(func(*ar, **kwar))
try:
yield
finally:
del globals()[reduce.__name__]
for func in funcs: globals()[func.__name__] = func
Con un uso que se parece a esto:
with noiters(map):
from operator import add
print(reduce(add, range(1, 20)))
print(map(int, ['1', '2']))
Que imprime:
190
[1, 2]
Solo mis 2 centavos: -)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-31 09:50:18
Dado que el método reduce
ha sido eliminado de la función incorporada de Python3, no olvide importar el functools
en su código. Por favor, mira el fragmento de código a continuación.
import functools
my_list = [10,15,20,25,35]
sum_numbers = functools.reduce(lambda x ,y : x+y , my_list)
print(sum_numbers)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-25 04:23:03