les itérateurs en Python

02 May 2019 02 May 2019 10258 vues ESSADDOUKI Mostafa 7 min de lecture

Itérateurs et protocole d'itération

En Python, un itérateur est tout objet pouvant être parcouru avec une boucle for. Les listes, tuples, dictionnaires, ensembles et chaînes sont des itérateurs intégrés car ils implémentent le protocole d'itération.

Définition — Protocole d'itérationTout objet souhaitant être itérable doit implémenter deux méthodes spéciales :
  • __iter__() : appelée à l'initialisation de l'itération. Doit retourner l'objet itérateur lui-même.
  • __next__() : retourne la valeur suivante. Doit lever StopIteration quand la séquence est épuisée.
La boucle for en coulisses Écrire for x in objest strictement équivalent à :
it = iter(obj)          # appelle obj.__iter__()
while True:
    try:
        x = next(it)    # appelle it.__next__()
        # traitement de x
    except StopIteration:
        break           # fin de l'itération

Itérateurs intégrés en Python

Python fournit plusieurs types itérables nativement. En voici un aperçu comparatif :

TypeSyntaxeOrdonné ?Modifiable ?
list[a, b, c]✅ Oui✅ Oui
tuple(a, b, c)✅ Oui❌ Non
str"abc"✅ Oui❌ Non
dict{"k": v}✅ Oui (≥ 3.7)✅ Oui
set{a, b, c}❌ Non✅ Oui
rangerange(n)✅ Oui❌ Non

Exemple — Parcours d'une liste

jours = ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche']
for jour in jours:
    print(jour, end="  ")
Sortie
Lundi  Mardi  Mercredi  Jeudi  Vendredi  Samedi  Dimanche

Exemple — Parcours d'un dictionnaire

personne = {'nom': 'ESSADDOUKI', 'prenom': 'Mostafa', 'annee': 2019}

for cle, valeur in personne.items():
    print(f"{cle:10} : {valeur}")
Sortie
nom        : ESSADDOUKI
prenom     : Mostafa
annee      : 2019

Exemple — Parcours d'une chaîne

msg = 'Bonjour'
for lettre in msg:
    print(lettre, end="-")   # B-o-n-j-o-u-r-

Définir un itérateur personnalisé


Syntaxe — Itérateur personnalisé Python
class MonIterateur:
    def __init__(self, données):
        self.données = données

    def __iter__(self):
        self.index = 0          # réinitialise à chaque boucle for
        return self

    def __next__(self):
        if self.index >= len(self.données):
            raise StopIteration
        valeur = self.données[self.index]
        self.index += 1
        return valeur

Exemple — Classe Tableau itérable

class Tableau:
    def __init__(self):
        self.tab = []

    def inserer(self, elm):
        self.tab.append(elm)

    def __iter__(self):
        self.i = 0
        return self

    def __next__(self):
        if self.i >= len(self.tab):
            raise StopIteration
        valeur = self.tab[self.i]
        self.i += 1
        return valeur

Tab = Tableau()
for val in [1, 2, 9, 3, 12, 4, 5]:
    Tab.inserer(val)

for elm in Tab:
    print(elm, end="  ")
Sortie
1  2  9  3  12  4  5

Exemple — Itérateur de suite arithmétique

class SuiteArith:
    """Génère la suite : debut, debut+pas, debut+2*pas, ... jusqu'à fin."""
    def __init__(self, debut, fin, pas=1):
        self.courant = debut
        self.fin     = fin
        self.pas     = pas

    def __iter__(self):
        return self

    def __next__(self):
        if self.courant > self.fin:
            raise StopIteration
        valeur       = self.courant
        self.courant += self.pas
        return valeur

for n in SuiteArith(0, 10, 2):
    print(n, end="  ")   # 0  2  4  6  8  10
Sortie
0  2  4  6  8  10
Astuce — Itérateur vs Générateur Pour des itérateurs simples, un générateur avec yield est plus concis qu'une classe avec __iter__ / __next__:
def suite_arith(debut, fin, pas=1):
    while debut <= fin:
        yield debut
        debut += pas

for n in suite_arith(0, 10, 2):
    print(n, end="  ")   # 0  2  4  6  8  10

Module itertools

Le module itertools fournit un ensemble de fonctions pour créer des itérateurs efficaces inspirés de la programmation fonctionnelle. Ces outils permettent d'écrire des boucles rapides et expressives.

FonctionDescriptionCatégorie
accumulate(iter, func)Accumulation successive (somme, produit, etc.)Transformation
chain(iter1, iter2)Concaténer plusieurs itérablesCombinaison
islice(iter, debut, fin, pas)Découper un itérable comme un sliceSélection
permutations(iter, r)Toutes les permutations de taille rCombinatoire
combinations(iter, r)Combinaisons sans répétition de taille rCombinatoire
combinations_with_replacement(iter, r)Combinaisons avec répétition de taille rCombinatoire

accumulate(iter, func)

Applique func de façon cumulative sur les éléments de l'itérable et retourne les résultats intermédiaires. Par défaut (sans func), effectue une somme cumulée.


Syntaxe Python
itertools.accumulate(iterable, func=operator.add)

Exemple 1 — Produit cumulé

import itertools

def produit(prec, courant):
    return prec * courant

liste = [1, 2, 5, 8, 9]
res   = itertools.accumulate(liste, produit)
print(list(res))
Sortie
[1, 2, 10, 80, 720]

Exemple 2 — Somme cumulée sur un itérateur personnalisé

import itertools

Tab = Tableau()
for val in [1, 2, 3, 4, 5, 6, 7]:
    Tab.inserer(val)

res = itertools.accumulate(Tab)   # somme cumulée par défaut
print(list(res))
Sortie
[1, 3, 6, 10, 15, 21, 28]

Exemple 3 — Masse salariale cumulée

import itertools

class Personne:
    def __init__(self, nom, salaire):
        self.nom     = nom
        self.salaire = salaire

class Ecole:
    def __init__(self):
        self.profs = []

    def ajouter(self, p):
        self.profs.append(p)

    def __iter__(self):
        self.i = 0
        return self

    def __next__(self):
        if self.i >= len(self.profs):
            raise StopIteration
        s = self.profs[self.i].salaire
        self.i += 1
        return s

ec = Ecole()
ec.ajouter(Personne('Mohamed', 8000))
ec.ajouter(Personne('Ahmed',   7000))
ec.ajouter(Personne('Sara',    7500))
ec.ajouter(Personne('Kaoutar', 5000))

res = itertools.accumulate(ec)
print(list(res))   # masse salariale cumulée
Sortie
[8000, 15000, 22500, 27500]

chain(iter1, iter2, ...)

Concatène plusieurs itérables en un seul flux, sans créer de liste intermédiaire. Équivalent à parcourir iter1, puis iter2, etc.

Exemple

import itertools

L1 = [1, 6, 5, 9]
L2 = [8, 10, 5, 4]
L3 = [3, 7]

res = list(itertools.chain(L1, L2, L3))
print(res)
Sortie
[1, 6, 5, 9, 8, 10, 5, 4, 3, 7]

islice(iterable, debut, fin, pas)

Extrait une tranche d'un itérable, comme le slicing sur les listes, mais applicable à tout itérable (même infini).


Syntaxe Python
itertools.islice(iterable, fin)
itertools.islice(iterable, debut, fin)
itertools.islice(iterable, debut, fin, pas)

Exemple 1 — Tranche d'une liste

import itertools

L1  = [1, 6, 5, 9, 3, 7, 2]
res = list(itertools.islice(L1, 1, 6, 2))
print(res)
Sortie
[6, 9, 7]

Exemple 2 — Tranche d'un itérateur personnalisé

import itertools

Tab = Tableau()
for val in [1, 2, 3, 4, 5, 6, 7]:
    Tab.inserer(val)

res = list(itertools.islice(Tab, 2, 7, 2))
print(res)
Sortie
[3, 5, 7]

Fonctions combinatoires

itertools propose trois fonctions pour générer des combinaisons et permutations — très utiles en mathématiques et algorithmique.

FonctionRépétitionOrdre important ?Résultat sur [1,2,5], r=2
permutations❌ Non✅ Oui(1,2)(1,5)(2,1)(2,5)(5,1)(5,2)
combinations❌ Non❌ Non(1,2)(1,5)(2,5)
combinations_with_replacement✅ Oui❌ Non(1,1)(1,2)(1,5)(2,2)(2,5)(5,5)

Exemple — Les trois fonctions côte à côte

import itertools

liste = [1, 2, 5]

print("Permutations (r=2) :")
print(list(itertools.permutations(liste, 2)))

print("\nCombinaisons sans répétition (r=2) :")
print(list(itertools.combinations(liste, 2)))

print("\nCombinaisons avec répétition (r=2) :")
print(list(itertools.combinations_with_replacement(liste, 2)))
Sortie
Permutations (r=2) :
[(1, 2), (1, 5), (2, 1), (2, 5), (5, 1), (5, 2)]

Combinaisons sans répétition (r=2) :
[(1, 2), (1, 5), (2, 5)]

Combinaisons avec répétition (r=2) :
[(1, 1), (1, 2), (1, 5), (2, 2), (2, 5), (5, 5)]
Astuce — Nombre de résultats Pour un itérable de taille n et un groupe de taille r:
  • permutations → P(n, r) = n! / (n−r)!
  • combinations → C(n, r) = n! / (r! × (n−r)!)
  • combinations_with_replacement → C(n+r−1, r)
Exemple : n=3, r=2 → P=6, C=3, C_rep=6.

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.