Iterators

Python SELF FR
Niveau 19 , Leçon 4
Disponible

5.1 Iterable et Iterator

Comme tu le sais déjà, les itérateurs sont des objets qui implémentent le protocole de l'itérateur, permettant de récupérer séquentiellement les éléments d'une collection. Les itérateurs sont largement utilisés en Python pour parcourir les éléments de séquences comme les listes, tuples et chaînes.

Voyons comment fonctionnent les itérateurs et comment les utiliser.

Objet itérable (Iterable)

Pour qu'un objet puisse être parcouru avec une boucle for, il doit être itérable – un Iterable. Cela signifie que notre objet doit implémenter la méthode __iter__(), qui retourne un objet itérateur.

Objet itérateur (Iterator)

C'est un objet spécial qui possède la fonction __next__() pour donner l'élément suivant de la séquence. Quand tous les éléments sont épuisés, la méthode __next__() déclenche une exception StopIteration comme signal d'arrêt d'itération.

L'itérateur doit aussi implémenter la méthode __iter__(), qui renvoie l'itérateur lui-même.

Exemple avec les fonctions intégrées de Python

Dans cet exemple, la liste numbers est un objet itérable. Nous obtenons un itérateur grâce à la fonction iter() et utilisons la fonction next() pour parcourir les éléments jusqu'à ce que l'exception StopIteration soit levée.


# Objet itérable
numbers = [1, 2, 3, 4, 5]
            
# Obtenir un itérateur à partir de l'itérable
iterator = iter(numbers)
            
# Utiliser l'itérateur pour parcourir les éléments
try:
    while True:
        number = next(iterator)
        print(number)
except StopIteration:
    pass
        

C'est exactement ce qui se passe quand tu écris du code comme :


# Objet itérable
numbers = [1, 2, 3, 4, 5]
            
for number in numbers:
    print(number)
        

5.2 L'essence d'un itérateur

Un itérateur est un certain objet qui nous aide à parcourir séquentiellement un groupe d'éléments. Les implémentations peuvent être très variées. Écrivons notre propre classe, où nous implémenterons toutes les exigences requises pour un itérateur.

Étape 1. Créons d'abord notre classe

Disons qu'elle retourne séquentiellement les nombres de start à end.


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
        

Étape 2. Support de la fonction __iter__

Maintenant, nous devons lui ajouter une fonction __iter__, qui renverra un objet itérateur sur lequel sera appelée la fonction __next()__. Nous retournerons une référence sur notre propre objet – ce qui est autorisé.


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
        
    def __iter__(self):
        return self
        

Étape 3. Support de la fonction __next__

Nous devons maintenant ajouter à notre objet itérateur la fonction __next__, qui renverra le prochain élément de notre liste. Nous utiliserons simplement la variable current :


def __next__(self):
    current = self.current
    self.current += 1
    return current
        

Étape 4. Arrêt de l'itérateur

Si l'itérateur a déjà retourné toutes les valeurs qu'il prévoyait, il doit lancer une exception StopIteration. Ajustons un peu notre dernière fonction :


def __next__(self):
    if self.current >= self.end:
        raise StopIteration
    current = self.current
    self.current += 1
    return current
        

Super. Maintenant, nous pouvons utiliser notre itérateur. Voici un exemple de tout notre code :


class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
        
    def __iter__(self):
        return self
        
    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        current = self.current
        self.current += 1
        return current
        
# Créer une instance de l'itérateur personnalisé
my_iter = MyIterator(1, 5)
        
# Utiliser l'itérateur pour parcourir les éléments
for num in my_iter:
    print(num)

5.3 Un bon itérateur

Pourquoi l'itérateur de l'exemple précédent est-il mauvais ? Oui, c'est un itérateur, il fonctionne, mais il est trop basique. Avec lui, impossible de parcourir la même collection d'éléments avec plusieurs itérateurs en même temps.

Il serait plus judicieux d'écrire un code qui ne retourne pas une référence à lui-même dans la méthode __iter__, mais un objet séparé, qui délivrerait correctement tous les éléments.

Exemple :


class MyIterable:
    def __init__(self, data):
        self.data = data
    
    def __iter__(self):
        return MyIterator(self.data)
    
class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        item = self.data[self.index]
        self.index += 1
        return item
    
# Utilisation
my_iterable = MyIterable([1, 2, 3, 4])
for item in my_iterable:
    print(item)
    

Dans cet exemple, nous avons deux classes — la première reçoit une collection sur laquelle nous allons itérer. Et la seconde — c'est l'itérateur qui retourne les éléments de la collection dans la méthode next(). Il est aussi assez simple, mais c'est ainsi qu'il faut ajouter les itérateurs dans vos classes.

1
Опрос
Modules et paquets,  19 уровень,  4 лекция
недоступен
Modules et paquets
Modules et paquets
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION