Comment remplacer une boucle while infinie par un itérateur en Python?

Vous avez du code qui utilise une boucle while pour traiter itérativement des données parce qu’il comporte une fonction ou une condition de test inhabituelle qui ne tombe pas dans le schéma itératif habituel.

Un scénario assez commun dans les programmes comportant des E/S est d’écrire du code comme ceci:

taille_morceau = 8192

def lecteur(s):
    while True:
        donnee= s.recv(taille_morceau)
        if donnee == b'':
            break
        traiter_donnee(donnee)

Un tel code peut souvent être remplacé en utilisant la méthode iter(), comme suit:

def lecteur(s):
    for morceau in iter(lambda: s.recv(taille_morceau), b''):
        traiter_donnee(morceau)

Si vous êtes un peu sceptique que cela pourrait fonctionner, vous pouvez essayer un exemple similaire avec des fichiers. Par exemple:

>>> import sys
>>> f = open('/etc/passwd')
>>> for morceau in iter(lambda: f.read(10), ''):
...     n = sys.stdout.write(morceau)
...
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
daemon:*:1:1:System Services:/var/root:/usr/bin/false
_uucp:*:4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico
...
>>>

Une caractéristique peu connue de la fonction intégrée iter() est qu’elle accepte facultativement un objet appelable à zéro argument une valeur sentinelle (terminaison) comme entrées.

Lorsqu’il est utilisé de cette façon, il crée un itérateur qui appelle l’appelable fourni encore et encore jusqu’à ce qu’il retourne la valeur donnée en tant que sentinelle.

Cette approche particulière fonctionne bien avec certains types de fonctions appelées de façon répétée, telles que celles impliquant des E/S.

Par exemple, si vous voulez lire des données en morceaux à partir de sockets ou de fichiers, vous devez généralement exécuter des appels read() ou recv() répétés suivis d’un test de fin de fichier.

Ce code prend tout simplement ces deux caractéristiques et les combine en un seul appel iter(). L’utilisation de lambda dans la solution est nécessaire pour créer un appelable qui ne prend pas d’arguments, mais fournit quand même l’argument de taille souhaité à recv() ou read().

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here