Cómo usar el filtro, el mapa y la reducción en Python 3

filter , map y reduce trabajo perfectamente en Python 2. Aquí hay 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 los siguientes resultados:

 >>> filter(f, range(2, 25))  >>> map(cube, range(1, 11))  >>> reduce(add, range(1, 11)) Traceback (most recent call last): File "", line 1, in  reduce(add, range(1, 11)) NameError: name 'reduce' is not defined 

Agradecería que alguien me explicara por qué esto es así.

Captura de pantalla del código para mayor claridad:

Sesiones IDLE de Python 2 y 3 lado a lado

    Puedes leer sobre los cambios en Novedades de Python 3.0 . Debe leerlo detenidamente cuando pase de 2.x a 3.x, ya que se ha cambiado mucho.

    Toda la respuesta aquí son citas de la documentación.

    Vistas e iteradores en lugar de listas

    Algunas API conocidas ya no devuelven listas:

    • […]
    • map() iteradores de retorno map() y filter() . Si realmente necesita una lista, una solución rápida es, por ejemplo, list(map(...)) , pero una solución mejor 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 lo haga. No necesito una lista en absoluto. Particularmente complicado es map() invocado para los efectos secundarios de la función; la transformación correcta es usar un bucle for regular (ya que crear una lista sería un desperdicio).
    • […]

    Builtins

    • […]
    • Eliminado reduce() . Use functools.reduce() si realmente lo necesita; sin embargo, el 99 por ciento de las veces es más legible un bucle explícito for .
    • […]

    La funcionalidad del map y el filter se cambió intencionalmente para devolver los iteradores, y la reducción se eliminó de ser una función incorporada y se colocó en functools.reduce .

    Por lo tanto, para el filter y el map , puede envolverlos con list() para ver los resultados como lo hizo 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 del mapa y el filtro con expresiones de generadores o listas de comprensión. 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 son el 99 por ciento de las veces más fáciles de leer que de reducir, pero yo simplemente me functools.reduce con functools.reduce .

    Edición : la cifra del 99 por ciento se extrae directamente de la página What’s New In Python 3.0 de Guido van Rossum.

    Como una adición a las otras respuestas, esto suena como un buen caso de uso para un administrador de contexto que volverá a asignar los nombres de estas funciones a las que devuelven una lista e introducen 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 ve así:

     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 🙂

    Dado que el método de reduce se ha eliminado de la función incorporada de Python3, no olvide importar las functools en su código. Por favor, mire 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) 

    Estos son los ejemplos de funciones de filtro, mapa y reducción.

    números = [10,11,12,22,34,43,54,34,67,87,88,98,99,87,44,66]

    //Filtrar

    oddNumbers = list (filtro (lambda x: x% 2! = 0, números))

    imprimir (números impares)

    //Mapa

    multiplyOf2 = list (mapa (lambda x: x * 2, números))

    imprimir (multiplicarOf2)

    //Reducir

    La función de reducción, ya que no se usa comúnmente, se eliminó de las funciones integradas en Python 3. Todavía está disponible en el módulo functools, por lo que puede hacer:

    desde functools importar reducir

    sumOfNumbers = reduce (lambda x, y: x + y, números)

    imprimir (sumOfNumbers)