Rheinwerk Computing < openbook >

 
Inhaltsverzeichnis
1 Einleitung
2 Die Programmiersprache Python
Teil I Einstieg in Python
3 Erste Schritte im interaktiven Modus
4 Der Weg zum ersten Programm
5 Kontrollstrukturen
6 Dateien
7 Das Laufzeitmodell
8 Funktionen, Methoden und Attribute
9 Informationsquellen zu Python
Teil II Datentypen
10 Das Nichts – NoneType
11 Operatoren
12 Numerische Datentypen
13 Sequenzielle Datentypen
14 Zuordnungen
15 Mengen
16 Collections
17 Datum und Zeit
18 Aufzählungstypen – Enum
Teil III Fortgeschrittene Programmiertechniken
19 Funktionen
20 Modularisierung
21 Objektorientierung
22 Ausnahmebehandlung
23 Iteratoren
24 Kontextobjekte
25 Manipulation von Funktionen und Methoden
Teil IV Die Standardbibliothek
26 Mathematik
27 Kryptografie
28 Reguläre Ausdrücke
29 Schnittstelle zu Betriebssystem und Laufzeitumgebung
30 Kommandozeilenparameter
31 Dateisystem
32 Parallele Programmierung
33 Datenspeicherung
34 Netzwerkkommunikation
35 Debugging und Qualitätssicherung
36 Dokumentation
Teil V Weiterführende Themen
37 Anbindung an andere Programmiersprachen
38 Distribution von Python-Projekten
39 Grafische Benutzeroberflächen
40 Python als serverseitige Programmiersprache im WWW – ein Einstieg in Django
41 Wissenschaftliches Rechnen
42 Insiderwissen
43 Von Python 2 nach Python 3
A Anhang
Stichwortverzeichnis

Download:
- Beispielprogramme, ca. 464 KB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Python 3 von Johannes Ernesti, Peter Kaiser
Das umfassende Handbuch
Buch: Python 3

Python 3
Pfeil 23 Iteratoren
Pfeil 23.1 Comprehensions
Pfeil 23.1.1 List Comprehensions
Pfeil 23.1.2 Dict Comprehensions
Pfeil 23.1.3 Set Comprehensions
Pfeil 23.2 Generatoren
Pfeil 23.2.1 Subgeneratoren
Pfeil 23.2.2 Generator Expressions
Pfeil 23.3 Iteratoren
Pfeil 23.3.1 Verwendung von Iteratoren
Pfeil 23.3.2 Mehrere Iteratoren für dieselbe Instanz
Pfeil 23.3.3 Nachteile von Iteratoren gegenüber dem direkten Zugriff über Indizes
Pfeil 23.3.4 Alternative Definition für iterierbare Objekte
Pfeil 23.3.5 Funktionsiteratoren
Pfeil 23.4 Spezielle Generatoren – itertools
Pfeil 23.4.1 accumulate(iterable, [func])
Pfeil 23.4.2 chain([*iterables])
Pfeil 23.4.3 combinations(iterable, r)
Pfeil 23.4.4 combinations_with_replacement(iterable, r)
Pfeil 23.4.5 compress(data, selectors)
Pfeil 23.4.6 count([start, step])
Pfeil 23.4.7 cycle(iterable)
Pfeil 23.4.8 dropwhile(predicate, iterable)
Pfeil 23.4.9 filterfalse(predicate, iterable)
Pfeil 23.4.10 groupby(iterable, [key])
Pfeil 23.4.11 islice(iterable, [start], stop, [step])
Pfeil 23.4.12 permutations(iterable, [r])
Pfeil 23.4.13 product([*iterables], [repeat])
Pfeil 23.4.14 repeat(object, [times])
Pfeil 23.4.15 starmap(function, iterable)
Pfeil 23.4.16 takewhile(predicate, iterable)
Pfeil 23.4.17 tee(iterable, [n])
Pfeil 23.4.18 zip_longest([*iterables], [fillvalue])
 
Zum Seitenanfang

23.3    Iteratoren Zur vorigen ÜberschriftZur nächsten Überschrift

Sie sind bei der Lektüre dieses Buchs schon oft mit dem Begriff »iterierbares Objekt« konfrontiert worden, wissen bisher allerdings nur, dass Sie solche Instanzen beispielsweise mit einer for-Schleife durchlaufen oder bestimmten Funktionen wie list als Parameter übergeben können. In diesem Abschnitt werden wir uns nun mit den Hintergründen und Funktionsweisen dieser Objekte befassen.

Ein sogenannter Iterator ist eine Abstraktionsschicht, die es ermöglicht, die Elemente eines Containers[ 104 ](Ein Container ist dabei die Instanz eines Datentyps, der eine Menge von Elementen speichert. Beispiele für Container sind Listen, Mengen und Dictionarys. ) über eine standardisierte Schnittstelle aufzuzählen.

Dabei wird von den konkreten Eigenheiten des Containers, auf seine Elemente zuzugreifen, abstrahiert, sodass mit demselben Code beliebige iterierbare Objekte durchlaufen werden können. Wie der Container die Elemente speichert und wie sonst darauf zugegriffen werden kann, spielt dann keine Rolle mehr.

Die dazu festgelegte Schnittstelle heißt Iterator-Protokoll und ist folgendermaßen definiert:

Jede iterierbare Instanz muss eine parameterlose __iter__-Methode implementieren, die ein Iterator-Objekt zurückgibt. Das Iterator-Objekt muss ebenfalls eine __iter__-Methode besitzen, die einfach eine Referenz auf das Objekt selbst zurückgibt. Außerdem muss es eine __next__-Methode aufweisen, die bei jedem Aufruf das nächste Element des zu durchlaufenden Containers liefert. Ist das Ende der Iteration erreicht, muss die __next__-Methode die StopIteration-Exception mittels raise werfen.

Um die Iteration starten zu können, muss über die Built-in Function iter eine Referenz auf den Iterator ermittelt werden. Die Anweisung iter(objekt) ruft dabei die __iter__-Methode der Instanz objekt auf und reicht das Ergebnis als Rückgabewert an die aufrufende Ebene weiter. Von der zurückgegebenen Iterator-Instanz kann dann so lange die __next__-Methode aufgerufen werden, bis diese die StopIteration-Exception wirft.

Um mehr Licht in diese abstrakte Beschreibung zu bringen, werden wir eine Klasse entwickeln, die uns über die Fibonacci-Folge[ 105 ](Viele Prozesse in der Natur, wie beispielsweise die Anzahl von Samen einer Sonnenblumenblüte, lassen sich durch die Fibonacci-Zahlen beschreiben. Außerdem konvergiert der Quotient aufeinanderfolgender Elemente für große n gegen den Goldenen Schnitt (Φ = 1,618…), einem Verhältnis, das oft mit Schönheit assoziiert wird. ) iterieren lässt. Die Fibonacci-Folge ist eine Folge aus ganzen Zahlen, wobei jedes Element f(n) durch die Summe seiner beiden Vorgänger f(n–2) + f(n–1) berechnet werden kann. Die beiden ersten Elemente werden per Definition auf f(1) = f(2) = 1 gesetzt. Der Anfang der unendlichen Folge ist in Tabelle 23.1 dargestellt.

n 1 2 3 4 5 6 7 8 9 10 11 12 13 14
f(n) 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Tabelle 23.1    Die ersten 14 Elemente der Fibonacci-Folge

class Fibonacci:
def __init__(self, max_n):
self.MaxN = max_n
self.N = 0
self.A = 0
self.B = 0
def __iter__(self):
self.N = 0
self.A = 0
self.B = 1
return self
def __next__(self):
if self.N < self.MaxN:
self.N += 1
self.A, self.B = self.B, self.A + self.B
return self.A
else:
raise StopIteration

Unsere Klasse Fibonacci erwartet als Parameter für ihren Konstruktor die Nummer des Elements, nach dem die Iteration stoppen soll. Diese Nummer speichern wir in dem Attribut MaxN und zählen dann mit dem Attribut N, wie viele Elemente bereits zurückgegeben wurden. Um uns zwischen den __next__-Aufrufen die aktuelle Position in der Folge zu merken und um das nächste Element berechnen zu können, speichern wir das zuletzt zurückgegebene Element und seinen Nachfolger in den Attributen A und B der Fibonacci-Klasse. Wir werden keine separate Iterator-Klasse definieren und lassen deshalb die __iter__-Methode eine Referenz auf die Fibonacci-Instanz selbst, also self, zurückgeben.[ 106 ](Dies hat zur Folge, dass es nur einen Iterator auf jede Instanz der Klasse Fibonacci geben kann. Mehr dazu erfahren Sie auf den folgenden Seiten, insbesondere in Abschnitt 23.3.2, »Mehrere Iteratoren für dieselbe Instanz«. ) Außerdem müssen beim Beginn des Durchlaufens die Speicher für das letzte bzw. nächste Element mit ihren Anfangswerten 0 bzw. 1 belegt werden, und der N-Zähler muss auf 0 gesetzt werden. Die __next__-Methode kümmert sich um die Berechnung des aktuellen Elements der Folge und aktualisiert die Zwischenspeicher und den Zähler. Ist das Ende der gewünschten Teilfolge erreicht, wird StopIteration geworfen.

Die Klasse lässt sich nun mit allen Konstrukten verarbeiten, die das Iterator-Protokoll unterstützen, wie beispielsweise die for-Schleife und die Built-in Functions list oder sum:

>>> for f in Fibonacci(14):
... print(f, end=" ")
...
1 1 2 3 5 8 13 21 34 55 89 144 233 377
>>> list(Fibonacci(16))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
>>> sum(Fibonacci(60))
4052739537880

Mit einer kleinen Subklasse von Fibonacci können wir auch einen Iterator erzeugen, der uns die Verhältnisse zweier aufeinanderfolgender Fibonacci-Zahlen durchlaufen lässt. Dabei sieht man, dass sich die Quotienten dem Goldenen Schnitt nähern. Die Subklasse muss nur die __next__-Methode der Fibonacci-Klasse überschreiben und dann anstelle der Folgeelemente die Quotienten zurückgeben. Dabei kommt es uns zugute, dass wir im Attribut B bereits den Wert des nächsten Elements im Voraus berechnen. Die Implementation sieht dann folgendermaßen aus:

class GoldenerSchnitt(Fibonacci):
def __next__(self):
Fibonacci.__next__(self)
return self.B / self.A

Schon die ersten vierzehn Elemente dieser Folge lassen die Konvergenz erkennen. (Der Goldene Schnitt, bis auf sechs Nachkommastellen gerundet, lautet 1,618034.)

>>> for g in GoldenerSchnitt(14):
... print("{:.6f}".format(g), end=" ")
...
1.000000 2.000000 1.500000 1.666667 1.600000 1.625000 1.615385
1.619048 1.617647 1.618182 1.617978 1.618056 1.618026 1.618037

Es ist möglich, die __iter__-Methode eines iterierbaren Objekts als Generator zu implementieren. Im Falle unserer Fibonacci-Folge läuft diese Technik auf wesentlich eleganteren Code hinaus, weil wir uns nun nicht mehr den Status des Iterators zwischen den __next__-Aufrufen merken müssen und auch die explizite Definition von __next__ entfällt:

class Fibonacci2:
def __init__(self, max_n):
self.MaxN = max_n
def __iter__(self):
n = 0
a, b = 0, 1
for n in range(self.MaxN):
a, b = b, a + b
yield a

Instanzen der Klasse Fibonacci2 verhalten sich bei der Iteration genau wie die Lösung ohne Generatoransatz:

>>> list(Fibonacci2(10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

Allerdings lässt sich die Klasse GoldenerSchnitt nicht mehr so einfach als Subklasse von Fibonacci2 implementieren, da die Zwischenspeicherung der Werte und auch die __next__-Methode nun in dem Generator gekapselt sind.

 
Zum Seitenanfang

23.3.1    Verwendung von Iteratoren Zur vorigen ÜberschriftZur nächsten Überschrift

Nun haben Sie gelernt, wie Sie eine gültige Iterator-Schnittstelle in Ihren eigenen Klassen implementieren können. Wir werden diese Thematik jetzt von der anderen Seite betrachten und uns damit beschäftigen, wie die Benutzung dieser Iterator-Schnittstelle aussieht, damit Sie auch Funktionen schreiben können, die nicht Listen oder andere Sequenzen, sondern beliebige iterierbare Instanzen verarbeiten können.

Wir betrachten zu diesem Zweck eine einfache for-Schleife und werden dann hinter die Kulissen schauen, indem wir eine äquivalente Schleife ohne for programmieren werden, die explizit das Iterator-Protokoll benutzt:

>>> for i in range(10):
... print(i, end=" ")
...
0 1 2 3 4 5 6 7 8 9

Wie Sie bereits wissen, benötigen wir zum Durchlaufen einer Sequenz das dazugehörige Iterator-Objekt. Dieses liefert uns die Built-in Function iter, die, wie schon im vorangegangenen Abschnitt erklärt, die __iter__-Methode des übergebenen Objekts aufruft:

>>> iter(range(10))
<range_iterator object at 0x7f7ef190dab0>

Über die __next__-Methode des Iterator-Objekts ermitteln wir nun der Reihe nach alle Elemente. Dabei rufen wir die Methode __next__ nicht direkt auf, sondern verwenden die Built-in Function next. Der Aufruf next(i) ist dabei äquivalent zu i.__next__().

>>> i = iter(range(3))
>>> next(i)
0
>>> next(i)
1
>>> next(i)
2
>>> next(i)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration:

Wird i.__next__ nach dem Zurückgeben des letzten Elements erneut aufgerufen, wirft die Methode erwartungsgemäß die StopIteration-Exception.

Die Built-in Function next(iterator, [default]) hat einen optionalen Parameter default. Wird ein Wert für default übergeben, fängt die Built-in Function next die StopIteration-Exception ab und gibt den Wert von default zurück:

>>> i = iter(range(2))
>>> next(i, 111)
0
>>> next(i, 111)
1
>>> next(i, 111)
111
>>> next(i, 111)
111

Wenn wir die StopIteration-Exception selbst mit einer try/except-Anweisung abfangen, können wir die for-Schleife folgendermaßen nachbauen:

>>> i = iter(range(10))
>>> while True:
... try:
... print(next(i), end=" ")
... except StopIteration:
... break
...
0 1 2 3 4 5 6 7 8 9

Die for-Schleife in Python ist natürlich nicht wie in dem Beispiel implementiert, sondern in eine optimierte Routine des Python-Interpreters ausgelagert. Dadurch erlaubt der Iterator-Ansatz auch eine Geschwindigkeitssteigerung, weil die Iteration durch eine maschinennahe C-Schleife übernommen werden kann.

[»]  Hinweis

Steht in einer Generatorfunktion eine return-Anweisung, wird der so zurückgegebene Wert in der StopIteration gespeichert und kann über ihr Attribut value ausgelesen werden.

>>> def test():
... yield 10
... yield 20
... return 1337
...
>>> i = test()
>>> while True:
... try:
... print(next(i))
... except StopIteration as e:
... print("Return:", e.value)
... break
...
10
20
Return: 1337

Dabei ist return wert in einem Generator äquivalent zu raise StopIteration(wert).

Die for-Schleife kann auch über einen Iterator selbst iterieren und muss diesen nicht selbst erzeugen. Die folgenden beiden Schleifen sind also äquivalent:

>>> for i in range(3):
... print(i, end=" ")
...
0 1 2
>>> for i in iter(range(3)):
... print(i, end=" ")
...
0 1 2

Dass for dabei, wie in der alternativen while-Schleife verdeutlicht, noch einmal selbst iter aufruft, ist insofern kein Problem, als die __iter__-Methode eines Iterator-Objekts eine Referenz auf das Objekt selbst zurückgeben muss. Ist a ein Iterator-Objekt, gilt immer (a is iter(a)), wie das folgende Beispiel verdeutlicht:

>>> a = iter(range(10)) # einen range-Iterator erzeugen
>>> a is iter(a)
True

Im Gegensatz dazu muss die __iter__-Methode eines iterierbaren Objekts weder eine Referenz auf sich selbst noch immer dieselbe Iterator-Instanz zurückgeben:

>>> a = list((1, 2, 3)) # ein iterierbares Objekt erzeugen
>>> iter(a) is iter(a)
False
 
Zum Seitenanfang

23.3.2    Mehrere Iteratoren für dieselbe Instanz Zur vorigen ÜberschriftZur nächsten Überschrift

Im Umkehrschluss bedeutet dies, dass die Built-in Function iter bei Aufrufen für dasselbe iterierbare Objekt verschiedene Iteratoren zurückgeben kann, was auch sinnvoll ist, um beispielsweise eine Liste mit zwei verschiedenen Iteratoren zu durchlaufen:

>>> l = [1, 2, 3]
>>> for i in l:
... for j in l:
... print(i,j, end=", ")
... print()
...
1 1, 1 2, 1 3,
2 1, 2 2, 2 3,
3 1, 3 2, 3 3,

In diesem Beispiel wird jedes Element der Liste l mit jedem anderen Element der Liste kombiniert, und die entstehenden Paare werden ausgegeben. Dazu wurde jeweils eine for-Schleife verwendet.

Versuchen wir, denselben Code mit einer Instanz der Fibonacci-Klasse vom Anfang dieses Abschnitts auszuführen, erhalten wir ein anderes Ergebnis:

>>> l = Fibonacci(3)
>>> for i in l:
... for j in l:
... print(i,j, end=", ")
... print()
...
1 1, 1 1, 1 2,

Wir haben erwartet, dass auch hier jede der ersten drei Fibonacci-Zahlen 1,1,2, mit jeder anderen kombiniert, ausgegeben wird, also eine Ausgabe wie folgt:

1 1, 1 1, 1 2, 
1 1, 1 1, 1 2,
2 1, 2 1, 2 2,

Dieses abweichende Verhalten rührt daher, dass die __iter__-Methode der Klasse Fibonacci keinen neuen Iterator erzeugt, sondern eine Referenz auf das jeweilige Objekt selbst zurückgibt. Daher kann es zu einer Instanz der Klasse Fibonacci zur gleichen Zeit nur einen Iterator geben, den sich im oben dargestellten Beispiel die beiden for-Schleifen teilen müssen.

Der genaue Ablauf sieht folgendermaßen aus:

Die äußere Schleife initialisiert durch Aufruf der __iter__-Methode die Instanz l für die Iteration, das heißt, die Attribute l.N und l.A werden auf 0, das Attribut l.B wird auf 1 gesetzt. Dann wird durch Aufrufen der Methode __next__ die erste Fibonacci-Zahl 1 ermittelt und mit i referenziert.

Nun startet die innere Schleife, die ihrerseits wieder die __iter__-Methode der Instanz l ruft und dadurch erneut die Attribute l.N, l.A auf 0 und l.B auf 1 setzt. Anschließend durchläuft j in der inneren Schleife die ersten drei Fibonacci-Zahlen 1,1,2 und kombiniert sie mit dem Wert 1 von i. Nach der dritten Zahl wirft die Methode __next__ die StopIteration-Exception, sodass die innere Schleife stoppt.

Im Anschluss ruft die äußere Schleife erneut die Methode __next__ von l, die immer noch die StopIteration-Exception wirft, da das Ende des gemeinsamen Iterators schon in der inneren Schleife erreicht wurde. Damit endet das Programm an dieser Stelle.

Wie Sie sehen, kann unerwartetes Verhalten auftreten, wenn implizit ein Iterator über mehrere Schleifen geteilt wird. Abhilfe können wir dadurch schaffen, dass wir die Klasse Fibonacci so anpassen, dass sie bei jedem Aufruf von __iter__ ein neues Iterator-Objekt zurückgibt:

class Fibonacci3:
class FibonacciIterator:
def __init__(self, max_n):
self.MaxN = max_n
self.N, self.A, self.B = 0, 0, 1
def __iter__(self):
return self
def __next__(self):
if self.N < self.MaxN:
self.N += 1
self.A, self.B = self.B, self.A + self.B
return self.A
else:
raise StopIteration
def __init__(self, max_n):
self.MaxN = max_n
def __iter__(self):
return self.FibonacciIterator(self.MaxN)

Die neue Klasse Fibonacci3 definiert eine weitere Klasse FibonacciIterator, die das eigentliche Iterieren übernimmt und genauso definiert wurde wie die Klasse Fibonacci. Jedes Mal, wenn ein neuer Iterator über eine Instanz der Klasse Fibonacci3 angefordert wird, wird ein neues Objekt der Klasse FibonacciIterator erzeugt.

Dadurch liefern die beiden verschachtelten Schleifen von oben das erwartete Ergebnis:

>>> l = Fibonacci3(3)
>>> for i in l:
... for j in l:
... print(i,j, end=", ")
... print()
...
1 1, 1 1, 1 2,
1 1, 1 1, 1 2,
2 1, 2 1, 2 2,

Aufgrund dieser möglichen Probleme ist es grundsätzlich eine gute Idee, bei jedem Aufruf von __iter__ einen neuen Iterator zu erzeugen.

 
Zum Seitenanfang

23.3.3    Nachteile von Iteratoren gegenüber dem direkten Zugriff über Indizes Zur vorigen ÜberschriftZur nächsten Überschrift

Neben den schon angesprochenen Vorteilen, dass einmal geschriebener Code für alle Datentypen, die das Iterator-Interface implementieren, gilt und dass durch die maschinennahe Implementation der Schnittstelle die Ausführung der Programme beschleunigt werden kann, haben Iteratoren auch Nachteile.

Iteratoren eignen sich gut, um alle Elemente einer Sequenz zu durchlaufen und dies einheitlich für alle Container-Datentypen umzusetzen. Im Gegensatz dazu kann mit Indizes in beliebiger Reihenfolge lesend und schreibend auf die Elemente eines Containers zugegriffen werden, was mit dem Iterator-Ansatz nicht möglich ist.

Insofern lassen sich die Indizes nicht vollständig durch Iteratoren ersetzen, sondern werden für Spezialfälle durch sie ergänzt.

 
Zum Seitenanfang

23.3.4    Alternative Definition für iterierbare Objekte Zur vorigen ÜberschriftZur nächsten Überschrift

Neben der oben beschriebenen Definition für iterierbare Objekte gibt es eine weitere Möglichkeit, eine Klasse iterierbar zu machen. Da es bei vielen Folgen und Containern möglich ist, die Elemente durchzunummerieren und über ganzzahlige Indizes anzusprechen, ist ein Objekt schon dann iterierbar, wenn man seine Elemente über die __getitem__-Methode, also den []-Operator, über ganzzahlige Indizes ansprechen kann. Ruft man die Built-in Function iter mit einer solchen Instanz als Parameter auf, kümmert Python sich um die Erzeugung des Iterators.

Bei jedem Aufruf der __next__-Methode des erzeugten Iterators wird die __getitem__-Methode der iterierbaren Instanz aufgerufen, wobei immer eine Ganzzahl als Parameter übergeben wird. Die Zählung der übergebenen Indizes beginnt bei 0 und endet erst, wenn die __getitem__-Methode einen IndexError produziert, sobald ein ungültiger Index übergeben wurde.

Beispielsweise kann eine Klasse zum Iterieren über die ersten max_n Quadratzahlen folgendermaßen aussehen, wenn sie zudem noch die Bestimmung ihrer Länge mittels len unterstützt:

class Quadrate:
def __init__(self, max_n):
self.MaxN = max_n
def __getitem__(self, index):
index += 1 # 0*0 ist nicht sehr interessant...
if index > len(self) or index < 1:
raise IndexError
return index*index
def __len__(self):
return self.MaxN

Zur Demonstration dieses versteckten Iterators lassen wir uns eine Liste mit den ersten zwanzig Quadratzahlen ausgeben:

>>> list(Quadrate(20))
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256,
289, 324, 361, 400]
 
Zum Seitenanfang

23.3.5    Funktionsiteratoren Zur vorigen ÜberschriftZur nächsten Überschrift

Die letzte Möglichkeit, in Python auf Iteratoren zurückzugreifen, stellen sogenannte Funktionsiteratoren dar. Das sind Objekte, die eine bestimmte Funktion so lange aufrufen, bis diese einen besonderen Wert, den Terminator der Folge, zurückgibt.

Einen Funktionsiterator erzeugen Sie mit der Built-in Function iter, wobei Sie als ersten Parameter eine Referenz auf die Funktion, über die Sie iterieren möchten, und als zweiten Parameter den Wert des Terminators übergeben.

iter(funktion, terminator)

Ein gutes Beispiel ist die Methode readline des file-Objekts, die so lange den Wert der nächsten Zeile zurückgibt, bis das Ende der Datei erreicht wurde. Wenn sich keine weiteren Daten mehr hinter der aktuellen Leseposition der file-Instanz befinden, gibt readline einen leeren String zurück. Läge im aktuellen Arbeitsverzeichnis eine Datei namens freunde.txt, die die vier Namen "Lucas", "Florian", "Lars" und "John" in je einer separaten Zeile enthielte, könnten wir folgendermaßen über sie iterieren:

>>> datei = open("freunde.txt")
>>> for zeile in iter(datei.readline, ""):
... print(zeile.strip(), end=" ")
...
Lucas Florian Lars John
[»]  Hinweis

Dieses Beispiel dient nur der Veranschaulichung von Funktionsiteratoren. Über die Zeilen einer Datei können Sie auch direkt mit

>>> for zeile in datei:
... print(zeile.strip(), end=" ")

iterieren.

 


Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Python 3 Python 3
Jetzt Buch bestellen

 Buchempfehlungen
Zum Rheinwerk-Shop: Einstieg in Python
Einstieg in Python


Zum Rheinwerk-Shop: Python. Der Grundkurs
Python. Der Grundkurs


Zum Rheinwerk-Shop: Algorithmen mit Python
Algorithmen mit Python


Zum Rheinwerk-Shop: Objektorientierte Programmierung
Objektorientierte Programmierung


Zum Rheinwerk-Shop: Raspberry Pi. Das umfassende Handbuch
Raspberry Pi. Das umfassende Handbuch


Zum Rheinwerk-Shop: Roboter-Autos mit dem Raspberry Pi
Roboter-Autos mit dem Raspberry Pi


Zum Rheinwerk-Shop: Neuronale Netze programmieren mit Python
Neuronale Netze programmieren mit Python


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2020
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern