~~ Vous avez peut-être mal compris le comportement de l'instruction for en python, donc si vous avez une idée de pourquoi, je vous serais reconnaissant de bien vouloir me le faire savoir. ~~ Résolu.
Itérateur qui renvoie la même chaîne trois fois
iter.py
# coding: utf-8
class Iterator(object):
def __init__(self):
self.counter = 3
def __iter__(self):
return self
def next(self):
self.counter -= 1
if self.counter < 0:
raise StopIteration
return "Hourra!"
Vérification
>>> from iter import Iterator
>>> instance = Iterator()
>>> iterator = iter(instance)
>>> print iterator.next()
Hourra!
>>> print iterator.next()
Hourra!
>>> print iterator.next()
Hourra!
>>> print iterator.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "iter.py", line 13, in next
raise StopIteration
StopIteration
pour la déclaration est également possible
>>> for i in Iterator():
... print i
...
Hourra!
Hourra!
Hourra!
RunTimeIterator
qui hérite de ʻIterator et remplace la méthode
next` après avoir avancé l'itération d'origine une seule fois à l'initialisation
iter.py
# coding: utf-8
class Iterator(object):
def __init__(self):
self.counter = 3
def __iter__(self):
return self
def next(self):
self.counter -= 1
if self.counter < 0:
raise StopIteration
return "Hourra!"
class RunTimeIterator(Iterator):
def __init__(self):
super(RunTimeIterator, self).__init__()
for i in self:
print i
break
self.next = self.alter_next
def alter_next(self):
self.counter -= 1
if self.counter < 0:
raise StopIteration
return "C'est marrant!"
Vérification
>>> from iter import RunTimeIterator
>>> instance = RunTimeIterator()
Hourra!
>>> iterator = iter(instance)
>>> print iterator.next()
C'est marrant!
>>> print iterator.next()
C'est marrant!
>>> print iterator.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "iter.py", line 28, in alter_next
raise StopIteration
StopIteration
Maintenant, si vous déplacez ceci avec une instruction for,
>>> for i in RunTimeIterator():
... print i
...
Hourra!
Hourra!
Hourra!
Cela ne fonctionne pas pour une raison quelconque.
~~ Je ne sais pas.
Cela semble être un problème qui se produit lorsque vous essayez de remplacer directement la méthode next
, dans l'exemple ci-dessus, cela fonctionne normalement si vous maintenez la chaîne de caractères retournée dans la variable d'instance et la remplacez, et plus généralement la méthode next
implémente une autre méthode Cela fonctionne bien si vous essayez de le retourner et de le remplacer. ~~
En fait, si vous utilisez la fonction next ()
du build-in sans appeler directement la méthode next
, le même phénomène que l'instruction for se produit.
>>> from iter import RunTimeIterator
>>> instance = RunTimeIterator()
Hourra!
>>> iterator = iter(instance)
>>> print next(iterator)
Hourra!
>>> print next(iterator)
Hourra!
>>> print next(iterator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "iter.py", line 12, in next
raise StopIteration
StopIteration
Quant au comportement de l'instruction for, il semble qu'il soit mis en italique en utilisant la fonction next ()
sans appeler directement la méthode next
de l'objet itérateur.
La raison pour laquelle la fonction next ()
a été créée en premier lieu est que vous n'avez pas à appeler la méthode next
directement comme vous utilisez ʻiter ()ou
len ()au lieu d'appeler
iter ou
lendirectement. Il semble que ce soit à cause de cela (en plus, est-il pratique de le renommer en
next en python3?) [^ 1], il semble donc qu'il n'est pas recommandé d'appeler directement la méthode
next` de l'instance.
Après tout, le problème est que la méthode intégrée next ()
renvoie la méthode next
au moment de la définition de la classe, pas la méthode next
de l'instance au moment de l'itération. Apparemment, l'implémentation de l'itérateur est définie lorsque la classe est définie [^ 2].
Même si vous remplacez la méthode next
de l'instance, elle ne sera pas reflétée dans l'itérateur réel, et si vous réécrivez directement la méthode next
de la classe, cela fonctionnera.
python
class RunTimeIterator(Iterator):
def __init__(self):
super(RunTimeIterator, self).__init__()
for i in self:
print i
break
# self.next = self.alter_next
self.__class__.next = self.alter_next
def alter_next(self):
self.counter -= 1
if self.counter < 0:
raise StopIteration
return "C'est marrant!"
Cependant, si vous le remplacez au niveau de la classe, il en sera bien sûr ainsi lorsque vous créerez deux ou plusieurs instances.
>>> from iter import RunTimeIterator
>>> for i in RunTimeIterator():
... print i
...
Hourra!
C'est marrant!
C'est marrant!
>>> for i in RunTimeIterator():
... print i
...
C'est marrant!
C'est marrant!
C'est marrant!
La méthode next
ne peut pas être remplacée directement, donc assurez-vous que la méthode next
renvoie une implémentation d'une autre méthode, et remplacez-la lorsque vous souhaitez la remplacer.
Dans l'exemple suivant, la méthode next
renvoie le résultat de la méthode _next
et lorsque vous souhaitez remplacer la méthode next
, vous remplacez la méthode _next
.
class RunTimeIterator(Iterator):
def __init__(self):
super(RunTimeIterator, self).__init__()
for i in self:
print i
break
self._next = self.alter_next
def next(self):
"""Réel`next`C'est une méthode, mais le contenu est`_next`
"""
return self._next()
def _next(self):
"""Substantiel`next`Méthode
Comme état initial du parent`next`Essayez d'utiliser la méthode.
`_next`Au lieu de définir une méthode`__init__`À
self._next = super(RunTimeIterator, self).next
C'est la même chose même si c'est écrit.
"""
return super(RunTimeIterator, self).next()
def alter_next(self):
self.counter -= 1
if self.counter < 0:
raise StopIteration
return "C'est marrant!"
>>> from iter import RunTimeIterator
>>> for i in RunTimeIterator():
... print i
...
Hourra!
C'est marrant!
C'est marrant!
>>> for i in RunTimeIterator():
... print i
...
Hourra!
C'est marrant!
C'est marrant!
À l'origine, je souhaite écrire un analyseur qui analyse la zone correspondant à l'en-tête à partir d'un fichier d'un certain format, puis ne récupère que les données nécessaires pour chaque ligne avec une classe qui hérite de file
, et remplace la méthode next
. J'ai rencontré ce problème lorsque j'essayais quelque chose.
Recommended Posts