704 votes

Créer un itérateur de base Python

Comment on créerait une fonction itérative (ou objet itérateur) en python ?

771voto

ars Points 35803

Itérateur objets en python sont conformes à l'itérateur protocole, ce qui signifie qu'ils fournissent deux méthodes: __iter__() et next(). L' __iter__ renvoie l'itérateur de l'objet et est implicitement appelé au début de la boucle. L' next() méthode renvoie la valeur suivante et est implicitement appelée à chaque tour de boucle d'incrément. next() soulève une exception StopIteration quand il n'y a pas plus de valeur de retour, ce qui est implicitement capturé par les boucles d'arrêt de l'itération.

Voici un exemple simple d'un compteur:

class Counter:
    def __init__(self, low, high):
        self.current = low
        self.high = high

    def __iter__(self):
        return self

    def next(self): # Python 3: def __next__(self)
        if self.current > self.high:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1


for c in Counter(3, 8):
    print c

Ce sera d'impression:

3
4
5
6
7
8

C'est plus facile à écrire à l'aide d'un générateur comme indiqué dans une réponse précédente:

def counter(low, high):
    current = low
    while current <= high:
        yield current
        current += 1

for c in counter(3, 8):
    print c

La sortie imprimée sera le même. Sous le capot, l'objet du générateur prend en charge l'itérateur protocole et fait quelque chose d'à peu près semblable au Comptoir de la classe.

David Mertz de l'article, les Itérateurs et Simple des Générateurs, est une très bonne introduction.

543voto

Ethan Furman Points 12683

Il existe quatre façons de construire un processus itératif de la fonction:

Exemples:

# generator
def uc_gen(text):
    for char in text:
        yield char.upper()

# generator expression
def uc_genexp(text):
    return (char.upper() for char in text)

 # iterator protocol
 class uc_iter():
     def __init__(self, text):
         self.text = text
         self.index = 0
     def __iter__(self):
         return self
     def __next__(self):
         try:
             result = self.text[self.index].upper()
         except IndexError:
             raise StopIteration
         self.index += 1
         return result

 # getitem method
 class uc_getitem():
     def __init__(self, text):
         self.text = text
     def __getitem__(self, index):
         result = self.text[index].upper()
         return result

Pour voir tous les quatre méthodes en action:

for iterator in uc_gen, uc_genexp, uc_iter, uc_getitem:
    for ch in iterator('abcde'):
        print ch,
    print

Qui se traduit par:

A B C D E
A B C D E
A B C D E
A B C D E

132voto

Manux Points 1027

Je vois que tu fais des en . Je voulais juste noter que lui-même peut être un générateur (éliminant ainsi la nécessité de et d’élever `` exceptions)

Bien sûr ici on pourrait faire ainsi directement un générateur, mais pour les classes plus complexes, il peut être utile.

105voto

akdom Points 6724

Tout d'abord le module itertools est incroyablement utile pour toutes sortes de cas dans lesquels un itérateur serait utile, mais ici, c'est tout ce que vous devez créer un itérateur en python:

rendement

N'est-ce pas cool? Le rendement peut être utilisé pour remplacer un normal de retour dans une fonction. Il renvoie l'objet tout de même, mais au lieu de détruire l'etat et à la sortie, il économise de l'état pour lorsque vous souhaitez exécuter la prochaine itération. Voici un exemple de cela dans l'action tiré directement de la itertools liste des fonctions:

 def count(n=0):
     while True:
         yield n
         n += 1

Comme indiqué dans la description des fonctions (c'est le comte (le) de la fonction du module itertools...) , il produit un itérateur qui renvoie des nombres entiers consécutifs n.

Générateur d'expressions sont une toute autre boîte de pandore (génial vers!). Ils peuvent être utilisés à la place d'une Compréhension de Liste pour économiser de la mémoire (liste des compréhensions de créer une liste dans la mémoire, est détruit après utilisation si pas affectée à une variable, mais générateur d'expressions peuvent créer un Objet de Générateur... ce qui est une façon élégante de dire Itérateur). Voici un exemple d'un générateur définition de l'expression:

gen = (n for n in xrange(0,11))

Ceci est très similaire à notre itérateur définition ci-dessus, à l'exception de la gamme complète est prédéterminé entre 0 et 10.

Je viens de trouver xrange() (surpris, je ne l'avais pas vu avant...) et de l'ajouter à l'exemple ci-dessus. xrange() est un objet iterable version de la gamme (de) qui a l'avantage de ne pas pré-création de la liste. Il serait très utile si vous avez un géant corpus de données pour effectuer une itération sur et seulement eu autant de mémoire pour le faire.

15voto

guyminuslife Points 141

Additif au message des ars : l’exemple de code, il prévoit le compteur fonctionne en Python 2.x, mais pas en Python 3.x. En Python 3.x, vous devez définir la méthode , pas . Sinon c’est à peu près le même AFAIK.

Source : PEP 3114

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X