Comment on créerait une fonction itérative (ou objet itérateur) en python ?
Réponses
Trop de publicités?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.
Il existe quatre façons de construire un processus itératif de la fonction:
- créer un générateur qui utilise le mot clé yield)
- utiliser un générateur d'expression (genexp)
- créer un itérateur (définit
__iter__
et__next__
(ounext
en Python 2.x)) - créer une fonction Python peut itérer sur son propre (définit
__getitem__
)
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
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.
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