569 Stimmen

Was sind Iterator, Iterable und Iteration?

Was sind "Iterable", "Iterator" und "Iteration" in Python? Wie sind sie definiert?

11voto

Nikolay Dudaev Punkte 372

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.

7voto

Kimvais Punkte 36440

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

7voto

techkuz Punkte 2988

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ückgibt self .

Daher sind Iteratoren auch iterierbar, aber Iterablen sind keine Iteratoren.

Luciano Ramalho, Fließendes Python.

6voto

Vicrobot Punkte 3491

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

5voto

Yilmaz Punkte 12859

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X