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.
__iter__(): appelée à l'initialisation de l'itération. Doit retourner l'objet itérateur lui-même.__next__(): retourne la valeur suivante. Doit leverStopIterationquand la séquence est épuisée.
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érationItérateurs intégrés en Python
Python fournit plusieurs types itérables nativement. En voici un aperçu comparatif :
| Type | Syntaxe | Ordonné ? | 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 |
range | range(n) | ✅ Oui | ❌ Non |
Exemple — Parcours d'une liste
jours = ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche']
for jour in jours:
print(jour, end=" ")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}")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é
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 valeurExemple — 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=" ")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 100 2 4 6 8 10
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 10Module 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.
| Fonction | Description | Catégorie |
|---|---|---|
accumulate(iter, func) | Accumulation successive (somme, produit, etc.) | Transformation |
chain(iter1, iter2) | Concaténer plusieurs itérables | Combinaison |
islice(iter, debut, fin, pas) | Découper un itérable comme un slice | Sélection |
permutations(iter, r) | Toutes les permutations de taille r | Combinatoire |
combinations(iter, r) | Combinaisons sans répétition de taille r | Combinatoire |
combinations_with_replacement(iter, r) | Combinaisons avec répétition de taille r | Combinatoire |
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.
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))[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))[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[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)[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).
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)[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)[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.
| Fonction | Répétition | Ordre 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)))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)]
permutations→ P(n, r) = n! / (n−r)!combinations→ C(n, r) = n! / (r! × (n−r)!)combinations_with_replacement→ C(n+r−1, r)
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.