~~ Möglicherweise haben Sie das Verhalten der for-Anweisung in Python falsch verstanden. Wenn Sie also eine Idee haben, warum, wäre ich Ihnen dankbar, wenn Sie mich wissen lassen könnten. ~~ Gelöst.
Iterator, der dreimal dieselbe Zeichenfolge zurückgibt
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 "Hurra!"
Bestätigung
>>> from iter import Iterator
>>> instance = Iterator()
>>> iterator = iter(instance)
>>> print iterator.next()
Hurra!
>>> print iterator.next()
Hurra!
>>> print iterator.next()
Hurra!
>>> print iterator.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "iter.py", line 13, in next
raise StopIteration
StopIteration
für Aussage ist auch möglich
>>> for i in Iterator():
... print i
...
Hurra!
Hurra!
Hurra!
RunTimeIterator
, derIterator
erbt und die next
-Methode ersetzt, nachdem die ursprüngliche Iteration bei der Initialisierung nur einmal vorgerückt wurde
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 "Hurra!"
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 "Es macht Spaß!"
Bestätigung
>>> from iter import RunTimeIterator
>>> instance = RunTimeIterator()
Hurra!
>>> iterator = iter(instance)
>>> print iterator.next()
Es macht Spaß!
>>> print iterator.next()
Es macht Spaß!
>>> 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
Wenn Sie dies nun mit einer for-Anweisung verschieben,
>>> for i in RunTimeIterator():
... print i
...
Hurra!
Hurra!
Hurra!
Es funktioniert aus irgendeinem Grund nicht.
~~ Ich weiß es nicht. Es scheint ein Problem zu sein, das auftritt, wenn Sie versuchen, die Methode "next" direkt zu ersetzen. Im obigen Beispiel funktioniert es normal, wenn Sie die zurückgegebene Zeichenfolge in der Instanzvariablen halten und ersetzen, und im Allgemeinen implementiert die Methode "next" eine andere Methode Es funktioniert gut, wenn Sie versuchen, es zurückzugeben und zu ersetzen. ~~
Wenn Sie die Funktion "next ()" des Einbaus verwenden, ohne die Methode "next" direkt aufzurufen, tritt tatsächlich das gleiche Phänomen wie bei der for-Anweisung auf.
>>> from iter import RunTimeIterator
>>> instance = RunTimeIterator()
Hurra!
>>> iterator = iter(instance)
>>> print next(iterator)
Hurra!
>>> print next(iterator)
Hurra!
>>> print next(iterator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "iter.py", line 12, in next
raise StopIteration
StopIteration
Das Verhalten der for-Anweisung scheint mit der Funktion next ()
kursiv geschrieben zu sein, ohne die Methode next
des Iteratorobjekts direkt aufzurufen.
Der Grund, warum die Funktion "next ()" überhaupt erst erstellt wurde, ist, dass Sie die Methode "next" nicht direkt aufrufen müssen, wie Sie "iter ()" und "len ()" verwenden, anstatt "iter" und "len" direkt aufzurufen. Es scheint, dass dies daran liegt (ist es außerdem zweckmäßig, es in Python3 in "next" umzubenennen?) [^ 1], so dass es anscheinend nicht empfohlen wird, die "next" -Methode der Instanz direkt aufzurufen.
Schließlich besteht das Problem darin, dass das integrierte "next ()" zum Zeitpunkt der Klassendefinition die "next" -Methode zurückgibt, nicht die "next" -Methode der Instanz zum Zeitpunkt der Iteration. Anscheinend wird die Iterator-Implementierung festgelegt, wenn die Klasse definiert wird [^ 2].
Selbst wenn Sie die "next" -Methode der Instanz ersetzen, wird sie nicht im eigentlichen Iterator wiedergegeben, und wenn Sie die "next" -Methode der Klasse direkt neu schreiben, funktioniert sie.
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 "Es macht Spaß!"
Wenn Sie es jedoch auf Klassenebene ersetzen, sieht es natürlich so aus, wenn Sie zwei oder mehr Instanzen erstellen.
>>> from iter import RunTimeIterator
>>> for i in RunTimeIterator():
... print i
...
Hurra!
Es macht Spaß!
Es macht Spaß!
>>> for i in RunTimeIterator():
... print i
...
Es macht Spaß!
Es macht Spaß!
Es macht Spaß!
Die next
-Methode kann nicht direkt ersetzt werden. Stellen Sie daher sicher, dass die next
-Methode eine Implementierung einer anderen Methode zurückgibt, und ersetzen Sie diese, wenn Sie sie ersetzen möchten.
Im folgenden Beispiel gibt die Methode "next" das Ergebnis der Methode "_next" zurück. Wenn Sie die Methode "next" ersetzen möchten, ersetzen Sie die Methode "_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):
"""Echt`next`Es ist eine Methode, aber der Inhalt ist`_next`
"""
return self._next()
def _next(self):
"""Wesentlich`next`Methode
Als Ausgangszustand des Elternteils`next`Versuchen Sie, die Methode zu verwenden.
`_next`Anstatt eine Methode zu definieren`__init__`Zu
self._next = super(RunTimeIterator, self).next
Es ist das gleiche, auch wenn es geschrieben ist.
"""
return super(RunTimeIterator, self).next()
def alter_next(self):
self.counter -= 1
if self.counter < 0:
raise StopIteration
return "Es macht Spaß!"
>>> from iter import RunTimeIterator
>>> for i in RunTimeIterator():
... print i
...
Hurra!
Es macht Spaß!
Es macht Spaß!
>>> for i in RunTimeIterator():
... print i
...
Hurra!
Es macht Spaß!
Es macht Spaß!
Ursprünglich möchte ich einen Parser schreiben, der den dem Header entsprechenden Bereich aus einer Datei eines bestimmten Formats in mehreren Zeilen analysiert und dann nur die erforderlichen Daten für jede Zeile in einer Klasse abruft und zurückgibt, die "Datei" erbt, und die "nächste" Methode ersetzt. Ich bin auf dieses Problem gestoßen, als ich etwas ausprobiert habe.
Recommended Posts