Was sind "Iterable", "Iterator" und "Iteration" in Python? Wie sind sie definiert?
Antworten
Zu viele Anzeigen?Ich weiß nicht, ob es jemandem hilft, aber ich visualisiere Konzepte immer gerne in meinem Kopf, um sie besser zu verstehen. Da ich einen kleinen Sohn habe, visualisiere ich das Konzept von Iterablen/Iteratoren mit Ziegelsteinen und weißem Papier.
Angenommen, wir befinden uns in einem dunklen Raum und auf dem Boden liegen Ziegelsteine für meinen Sohn. Ziegelsteine unterschiedlicher Größe, Farbe, das spielt jetzt keine Rolle. Nehmen wir an, wir haben 5 solcher Ziegelsteine. Diese 5 Ziegelsteine können beschrieben werden als ein Objekt - sagen wir mal Bausatz Ziegelsteine . Wir können viele Dinge mit diesem Baukasten machen - wir können einen Stein nehmen und dann den zweiten und dann den dritten, wir können die Plätze der Steine tauschen, den ersten Stein über den zweiten legen. Wir können viele verschiedene Dinge damit machen. Deshalb ist dieser Baukasten ein iterierbares Objekt o Reihenfolge denn wir können jeden Ziegelstein durchgehen und etwas mit ihm machen. Wir können es nur wie mein kleiner Sohn machen - wir können mit ihm spielen. un Ziegelstein zu einer Zeit . Also wieder stelle ich mir vor, dass dieser Ziegelbausatz ein iterierbar .
Denken Sie daran, dass wir uns in einem dunklen Raum befinden. Oder fast dunkel. Die Sache ist die, dass wir die Ziegelsteine nicht klar sehen können, welche Farbe sie haben, welche Form usw. Selbst wenn wir also etwas mit ihnen machen wollen - aka sie durchlaufen zu lassen - Wir wissen nicht wirklich, was und wie, weil es zu dunkel ist.
Wir können in der Nähe des ersten Ziegels - als Element eines Ziegelbausatzes - ein Stück weißes fluoreszierendes Papier anbringen, damit wir sehen können, wo sich das erste Ziegel-Element befindet. Und jedes Mal, wenn wir einen Ziegelstein aus dem Bausatz nehmen, legen wir das weiße Stück Papier auf den nächsten Ziegelstein, damit wir diesen im dunklen Raum sehen können. Dieses weiße Stück Papier ist nichts anderes als ein Iterator . Es ist ein Objekt auch . Aber ein Objekt, mit dem wir arbeiten können und spielen mit Elementen unserer iterable Objekt - Bausteine Kit.
Das erklärt übrigens meinen anfänglichen Fehler, als ich das Folgende in einem IDLE versuchte und einen TypeError erhielt:
>>> X = [1,2,3,4,5]
>>> next(X)
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
next(X)
TypeError: 'list' object is not an iterator
Liste X hier war unser Bausatz, aber NICHT ein weißes Blatt Papier. Ich musste zuerst einen Iterator finden:
>>> X = [1,2,3,4,5]
>>> bricks_kit = [1,2,3,4,5]
>>> white_piece_of_paper = iter(bricks_kit)
>>> next(white_piece_of_paper)
1
>>> next(white_piece_of_paper)
2
>>>
Ich weiß nicht, ob es hilft, aber mir hat es geholfen. Wenn jemand die Visualisierung des Konzepts bestätigen/korrigieren könnte, wäre ich sehr dankbar. Es würde mir helfen, mehr zu lernen.
Ich glaube nicht, dass es viel einfacher geht als mit dem Dokumentation aber ich werde es versuchen:
-
Iterierbar etwas sein kann, das iteriert vorbei. In der Praxis in der Regel bedeutet eine Reihenfolge z. B. etwas, das einen Anfang und ein Ende hat und eine Möglichkeit, alle Elemente darin durchzugehen.
-
Sie können denken Iterator als Hilfs-Pseudomethode (oder Pseudo-Attribut), die das nächste (oder erste) Element in der iterierbar . (In der Praxis ist es nur ein Objekt, das die Methode
next()
) -
Iteration wird wahrscheinlich am besten durch den Merriam-Webster erklärt Definition des Wortes :
b : die Wiederholung einer Folge von Computerbefehlen in einer bestimmten Anzahl von Wiederholungen oder bis eine Bedingung erfüllt ist - vgl. Rekursion
Iterables haben eine
__iter__
Methode, die jedes Mal einen neuen Iterator instanziiert.Iteratoren einführen
__next__
Methode, die einzelne Elemente zurückgibt, und eine__iter__
Methode, die Folgendes zurückgibtself
.Daher sind Iteratoren auch iterierbar, aber Iterablen sind keine Iteratoren.
Luciano Ramalho, Fließendes Python.
Iterierbar :- etwas, das iterierbar ist, ist iterierbar; wie Sequenzen, Listen, Strings usw. Außerdem hat es entweder die __getitem__
Methode oder eine __iter__
Methode. Wenn wir nun iter()
Funktion auf dieses Objekt anwenden, erhalten wir einen Iterator.
Iterator :- Wenn wir das Iterator-Objekt von der iter()
Funktion; wir rufen __next__()
Methode (in Python3) oder einfach next()
(in Python2), um die Elemente einzeln zu erhalten. Diese Klasse oder Instanz dieser Klasse wird als Iterator bezeichnet.
Aus den Unterlagen:-
Die Verwendung von Iteratoren durchdringt und vereinheitlicht Python. Hinter den Kulissen ruft die for-Anweisung iter()
auf das Container-Objekt. Die Funktion gibt ein Iterator-Objekt zurück, das die Methode __next__()
die auf die einzelnen Elemente des Containers zugreift. Wenn es keine Elemente mehr gibt, __next__()
löst eine StopIteration-Ausnahme aus, die die for-Schleife zum Beenden auffordert. Sie können die __next__()
Methode unter Verwendung der next()
eingebauten Funktion; dieses Beispiel zeigt, wie das Ganze funktioniert:
>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
next(it)
StopIteration
Ex einer Klasse:-
class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
... print(char)
...
m
a
p
s
Iteratoren sind Objekte, die die iter y nächste Methoden. Wenn diese Methoden definiert sind, können wir for-Schleifen oder Comprehensions verwenden.
class Squares:
def __init__(self, length):
self.length = length
self.i = 0
def __iter__(self):
print('calling __iter__') # this will be called first and only once
return self
def __next__(self):
print('calling __next__') # this will be called for each iteration
if self.i >= self.length:
raise StopIteration
else:
result = self.i ** 2
self.i += 1
return result
Iteratoren werden erschöpft. Das bedeutet, dass Sie nach der Iteration über Elemente nicht mehr wiederholen können, sondern ein neues Objekt erstellen müssen. Nehmen wir an, Sie haben eine Klasse, die die Eigenschaften der Städte enthält und die Sie durchlaufen wollen.
class Cities:
def __init__(self):
self._cities = ['Brooklyn', 'Manhattan', 'Prag', 'Madrid', 'London']
self._index = 0
def __iter__(self):
return self
def __next__(self):
if self._index >= len(self._cities):
raise StopIteration
else:
item = self._cities[self._index]
self._index += 1
return item
Die Instanz der Klasse Cities ist ein Iterator. Wenn Sie jedoch Städte wiederholen möchten, müssen Sie ein neues Objekt erstellen, was eine teure Operation ist. Sie können die Klasse in zwei Klassen aufteilen: eine gibt Städte zurück und die zweite gibt einen Iterator zurück, der die Städte als Init-Parameter erhält.
class Cities:
def __init__(self):
self._cities = ['New York', 'Newark', 'Istanbul', 'London']
def __len__(self):
return len(self._cities)
class CityIterator:
def __init__(self, city_obj):
# cities is an instance of Cities
self._city_obj = city_obj
self._index = 0
def __iter__(self):
return self
def __next__(self):
if self._index >= len(self._city_obj):
raise StopIteration
else:
item = self._city_obj._cities[self._index]
self._index += 1
return item
Wenn wir nun einen neuen Iterator erstellen müssen, brauchen wir die Daten nicht erneut zu erstellen, was die Städte betrifft. Wir erstellen das Objekt cities und übergeben es an den Iterator. Aber wir machen immer noch zusätzliche Arbeit. Wir könnten dies implementieren, indem wir nur eine Klasse erstellen.
Iterierbar ist ein Python-Objekt, das die Funktion iterierbares Protokoll . Sie erfordert nur __iter__()
die eine neue Instanz des Iterator-Objekts zurückgibt.
class Cities:
def __init__(self):
self._cities = ['New York', 'Newark', 'Istanbul', 'Paris']
def __len__(self):
return len(self._cities)
def __iter__(self):
return self.CityIterator(self)
class CityIterator:
def __init__(self, city_obj):
self._city_obj = city_obj
self._index = 0
def __iter__(self):
return self
def __next__(self):
if self._index >= len(self._city_obj):
raise StopIteration
else:
item = self._city_obj._cities[self._index]
self._index += 1
return item
Iteratoren hat __iter__
y __next__
haben Iterables __iter__
Wir können also sagen, dass Iteratoren auch Iterables sind, aber sie sind Iterables, die sich erschöpfen. Iterabeln hingegen werden nie erschöpft weil sie immer einen neuen Iterator zurückgeben, der dann zur Iteration verwendet wird
Wie Sie sehen, befindet sich der Hauptteil des Iterablen-Codes im Iterator, und die Iterable selbst ist nichts weiter als eine zusätzliche Schicht, die es uns ermöglicht, den Iterator zu erstellen und darauf zuzugreifen.
Iteration über eine Iterable
Python hat eine eingebaute Funktion iter() die die __iter__()
. Wenn wir über eine Iterable iterieren, ruft Python die iter() der einen Iterator zurückgibt, dann beginnt er mit __next__()
von Iterator, um die Daten zu iterieren.
Beachten Sie, dass im obigen Beispiel Cities eine Iterable erstellt, aber kein Sequenztyp ist, d. h. wir können eine Stadt nicht über einen Index abrufen. Um dies zu beheben, sollten wir einfach hinzufügen __get_item__
zur Klasse der Städte.
class Cities:
def __init__(self):
self._cities = ['New York', 'Newark', 'Budapest', 'Newcastle']
def __len__(self):
return len(self._cities)
def __getitem__(self, s): # now a sequence type
return self._cities[s]
def __iter__(self):
return self.CityIterator(self)
class CityIterator:
def __init__(self, city_obj):
self._city_obj = city_obj
self._index = 0
def __iter__(self):
return self
def __next__(self):
if self._index >= len(self._city_obj):
raise StopIteration
else:
item = self._city_obj._cities[self._index]
self._index += 1
return item