Le module itertools est un module bien pratique auquel on ne pense pas assez souvent. En tout cas auquel, moi, je ne pense pas assez souvent. Et pourtant, il peut grandement simplifier pas mal de ligne de code, dans un bon nombre de situation. Il faut juste savoir que les fonctions qu’il propose existe.
Ce billet a donc 2 objectifs, vous faire découvrir les itertools (je ne vais pas lister toutes les fonctions juste celles dont je devrais me servir plus souvent et que j’oublie) et me permettre de ne pas oublier que je pourrais les utiliser.
Point important : Un certain nombre des itertools permettent de gérer les iterateur infinis, ce que ne permettent pas les fonctions ‘normales’ comme map par exemple (qui renvoie une sortie complétement calculée, ce qui est par définition impossible avec un iterateur infini).
Précision : les exemples de code sont ceux fournis par la doc officielle des itertools
itertools.chain (*iterables)
permet d’avoir un iterateur qui retourne tout les éléments du premier iterable passé en paramètre, puis du second, puis du troisième, etc etc… Bien pratique pour aérer son code.
# chain('ABC', 'DEF') --> A B C D E F
for it in iterables:
for element in it:
yield element
Depuis python 2.6, il existe une classmethod de chain, from_iterable(iterable) qui ne prend qu’un argument, un iterable contenant tout les iterables.
def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
for element in it:
yield element
itertools.compress(data, selectors)
compress n’est disponible qu’en python 2.7. Cette fonction retourne un iterateur contenant que uniquement les valeurs de data auxquelles correspondent un élément évalué à True dans le selectors. Compress s’arrête dès que data ou selectors est vide.
# compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
return (d for d, s in izip(data, selectors) if s)
itertools.count(start=0, step=1)
Cette fonction bien que présente depuis longtemps a droit à quelques modifications dans python 2.7. Count gagne en effet l’argument step et la possibilité d’itérer sur des arguments non integer.
# count(10) --> 10 11 12 13 14 ...
# count(2.5, 0.5) -> 3.5 3.0 4.5 ...
n = start
while True:
yield n
n += step
itertools.dropwhile(predicate, iterable)
Construit un iterateur qui ne renvoie aucun élément de l’iterable tant que le prédicat est vrai, ensuite, tout les éléments de l’iterable sont renvoyés
# dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
iterable = iter(iterable)
for x in iterable:
if not predicate(x):
yield x
break
for x in iterable:
yield x
itertools.takewhile(predicate, iterable)
Construit un iterateur qui, tant que le prédicat est vrai, renvoie les éléments de l’iterable.
# takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
for x in iterable:
if predicate(x):
yield x
else:
break
itertools.ifilter(predicate, iterable) et itertools.ifilterfalse(predicate, iterable)
Construit un iterateur qui ne renvoie que les éléments pour lesquels le prédicat est respectivement True ou False. Si predicate est à None, l’iterateur renvoie les éléments respectivement True ou False.
# ifilter(lambda x: x%2, range(10)) --> 1 3 5 7 9
if predicate is None:
predicate = bool
for x in iterable:
if predicate(x):
yield x
itertools.imap(function, *iterables)
Renvoie un iterateur qui applique function en utilisant les iterables comme argument. Si function est None, les arguments sont retournés sous la forme d’un tuple. Imap s’arrête lorsqu’elle atteint la fin du plus petit des iterables. Imap est utile lorsque l’on utilise des iterateur infinie qui provoque une erreur avec map.
# imap(pow, (2,3,10), (5,2,3)) --> 32 9 1000
iterables = map(iter, iterables)
while True:
args = [next(it) for it in iterables]
if function is None:
yield tuple(args)
else:
yield function(*args)
les autres i-versions des fonctions classiques.
Comme l’on trouve imap, il existe aussi izip, izip_longest et islice,
Parmi les autres fonctions il y a des fonctions de combinaisons, de calcul, de cycle, de groupby, mais celles là, vous les trouverez sur la doc officielle.
2 Responses to “Petit tour du coté des itertools, billet sans nucléaire dedans, promis”
Sorry, the comment form is closed at this time.
Je crois qu’il y a une petite typo à la fin grouby devrait être remplacé par groupby
ha oui .. merci, je vais corriger ça tout de suite