Comment utiliser filter, map, and reduce en Python 3
filter
, map
, et reduce
fonctionne parfaitement en Python 2. Voici un exemple:
>>> 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
mais en Python 3, je reçois les sorties suivantes:
>>> 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
j'apprécierais que quelqu'un puisse m'expliquer pourquoi.
Capture d'écran de code pour plus de clarté:
4 réponses
vous pouvez lire à propos des changements dans Quoi de neuf en Python 3.0 . Vous devriez le lire attentivement lorsque vous déplacez de 2.x à 3.x depuis beaucoup de choses ont changé.
toute la réponse ici sont des citations de la documentation.
Vues Et Itérateurs Au Lieu Des Listes
certaines API bien connues ne renvoient plus de listes:
- [...]
map()
etfilter()
itérateurs de retour. Si vous avez vraiment besoin d'une liste, une solution rapide est par exemplelist(map(...))
, mais une meilleure solution est souvent d'utiliser une compréhension de liste (surtout lorsque le code original utilise lambda), ou réécrire le code de sorte qu'il n'a pas besoin d'une liste du tout. Particulièrement délicat estmap()
invoqué pour les effets secondaires de la fonction; le la transformation correcte consiste à utiliser une boucle régulièrefor
(puisque créer une liste serait juste un gaspillage).- [...]
- [...]
- supprimé
reduce()
. Utiliserfunctools.reduce()
si vous en avez vraiment besoin; cependant, 99% du temps une la boucle explicitefor
est plus lisible.- [...]
la fonctionnalité de map
et filter
a été modifiée intentionnellement pour retourner les itérateurs, et reduce a été retiré du fait qu'il s'agissait d'un système intégré et placé dans functools.reduce
.
ainsi, pour filter
et map
, vous pouvez les envelopper avec list()
pour voir les résultats comme vous l'avez fait avant.
>>> 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 recommandation est maintenant que vous remplaciez votre utilisation de map et de filter par des expressions ou des listes de générateurs compréhension. Exemple:
>>> 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]
>>>
ils disent que pour les boucles sont 99 pour cent du temps plus facile à lire que de réduire, Mais je m'en tiendrais simplement à functools.reduce
.
Edit : le chiffre de 99% est tiré directement de la page Quoi de neuf en Python 3.0 de Guido van Rossum.
comme addendum aux autres réponses, cela ressemble à un cas d'utilisation pour un gestionnaire de contexte qui va re-map les noms de ces fonctions à ceux qui renvoient une liste et introduisent reduce
dans l'espace de noms global.
une implémentation rapide pourrait ressembler à ceci:
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
avec un usage qui ressemble à ceci:
with noiters(map):
from operator import add
print(reduce(add, range(1, 20)))
print(map(int, ['1', '2']))
qui imprime:
190
[1, 2]
juste mes 2 cents :- )
depuis que la méthode reduce
a été retirée de la fonction intégrée de Python3, n'oubliez pas d'importer le functools
dans votre code. Veuillez consulter l'extrait de code ci-dessous.
import functools
my_list = [10,15,20,25,35]
sum_numbers = functools.reduce(lambda x ,y : x+y , my_list)
print(sum_numbers)