Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.
| Beide Seiten, vorherige Überarbeitung Vorherige Überarbeitung Nächste Überarbeitung | Vorherige Überarbeitung | ||
| talit:generators [2024-05-17 13:26] – hof | talit:generators [2025-08-15 07:36] (aktuell) – [Aufgabe 4: Pre-Order Traversierung] hof | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| # Iteratoren und Generatoren in Python | # Iteratoren und Generatoren in Python | ||
| + | < | ||
| + | |||
| Eine [[wpde> | Eine [[wpde> | ||
| Zeile 6: | Zeile 8: | ||
| Wir möchten wiederverwendbaren Code schreiben, der die [[wpde> | Wir möchten wiederverwendbaren Code schreiben, der die [[wpde> | ||
| + | |||
| ### Aufgabe 1: Fibonacci-Liste | ### Aufgabe 1: Fibonacci-Liste | ||
| Unser erster Versuch: Schreibe eine Funktion, die die ersten `n` Elemente der Fibonacci-Folge generiert und in einer Liste zurückgibt. Untenstehender Code funktioniert nur für $n\le10$ -- ändere den Code so, dass er für beliebig grosse $n$ das richtige Resultat zurückgibt! | Unser erster Versuch: Schreibe eine Funktion, die die ersten `n` Elemente der Fibonacci-Folge generiert und in einer Liste zurückgibt. Untenstehender Code funktioniert nur für $n\le10$ -- ändere den Code so, dass er für beliebig grosse $n$ das richtige Resultat zurückgibt! | ||
| - | < | + | < |
| - | "></iframe></ | + | |
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | print(fibonacci(10))</bottom-editor></ | ||
| <nodisp 0> | <nodisp 0> | ||
| Zeile 43: | Zeile 52: | ||
| Solche Strom-Objekte heissten _Iteratoren_. Ein Iterator hat nur eine einzige Funktion, `__next__`, die jeweils das nächste Element zurückgibt. Der Iterator muss sich irgendwie den Zustand merken, also wo in der Fibonacci-Folge er gerade steckt. Die Funktion wirft eine `StopIteration` Exception wenn es keine weiteren Elemente gibt. | Solche Strom-Objekte heissten _Iteratoren_. Ein Iterator hat nur eine einzige Funktion, `__next__`, die jeweils das nächste Element zurückgibt. Der Iterator muss sich irgendwie den Zustand merken, also wo in der Fibonacci-Folge er gerade steckt. Die Funktion wirft eine `StopIteration` Exception wenn es keine weiteren Elemente gibt. | ||
| - | Die _built-in function_ [next](https:// | + | Die _built-in function_ [next](https:// |
| - | . | + | |
| ### Aufgabe 2: Fibonacci-Iterator | ### Aufgabe 2: Fibonacci-Iterator | ||
| Analysiere den untenstehenden Code und führe ihn aus. Ändere den Code, so dass die erste Fibonacci Zahl ausgegeben wird, die grösser als 1000 ist! | Analysiere den untenstehenden Code und führe ihn aus. Ändere den Code, so dass die erste Fibonacci Zahl ausgegeben wird, die grösser als 1000 ist! | ||
| - | < | + | < |
| - | "></ | + | |
| + | # Constructor - hier wird der Initial-Zustand gespeichert | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| - | < | + | iterator = FiboIterator() |
| + | print(next(iterator)) | ||
| + | print(next(iterator)) | ||
| + | print(next(iterator))</ | ||
| + | |||
| + | |||
| + | < | ||
| ++++Lösung| | ++++Lösung| | ||
| <code python> | <code python> | ||
| Zeile 65: | Zeile 92: | ||
| ++++ | ++++ | ||
| </ | </ | ||
| + | |||
| ## Iterables | ## Iterables | ||
| Zeile 84: | Zeile 112: | ||
| Untenstehender Code fügt dem bestehenden Iterator ein Iterable hinzu, so dass wir eine for-Schleife nützen können: | Untenstehender Code fügt dem bestehenden Iterator ein Iterable hinzu, so dass wir eine for-Schleife nützen können: | ||
| - | < | + | < |
| - | "></iframe></ | + | |
| + | # Hier wird der Zustand gespeichert | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | class FiboIterable: | ||
| + | # Wird einmal aufgerufen, wenn Python die for-Schleife startet. | ||
| + | | ||
| + | | ||
| + | |||
| + | sequence = FiboIterable() | ||
| + | for num in sequence: | ||
| + | | ||
| + | | ||
| + | | ||
| + | </bottom-editor></ | ||
| + | |||
| + | Die Funktionen `__iter__` und `__next__` dürfen auch von derselben Klasse implementiert werden. | ||
| - | Die Funktionen `__iter__` und `__next__` dürfen auch von derselben Klasse implementiert werden | ||
| - | . | ||
| ## Yield | ## Yield | ||
| Zeile 97: | Zeile 149: | ||
| Ein Generator ist ein Iterable und kann damit auch als Ausdruck nach `in` in einer `for ... in < | Ein Generator ist ein Iterable und kann damit auch als Ausdruck nach `in` in einer `for ... in < | ||
| - | < | + | < |
| - | "></iframe></ | + | |
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | for num in fibo(): | ||
| + | | ||
| + | | ||
| + | | ||
| + | </bottom-editor></ | ||
| ### Iteration beenden | ### Iteration beenden | ||
| Sind keine Elemente mehr übrig, wird einfach nichts zurückgegeben bzw. ein normales `return`. | Sind keine Elemente mehr übrig, wird einfach nichts zurückgegeben bzw. ein normales `return`. | ||
| - | #### Aufgabe 3: Limitieren | + | ### Aufgabe 3: Limitieren |
| Verändere den obigen Code um ein optionales Limit einzubauen, wieviele Elemente erzeugt werden sollen. | Verändere den obigen Code um ein optionales Limit einzubauen, wieviele Elemente erzeugt werden sollen. | ||
| Zeile 109: | Zeile 171: | ||
| Der folgende Code soll also `143` ausgeben: | Der folgende Code soll also `143` ausgeben: | ||
| - | < | + | < |
| - | "></iframe></ | + | |
| + | |||
| + | n=10 | ||
| + | print(f' | ||
| + | </bottom-editor></ | ||
| ## Yield From | ## Yield From | ||
| Manchmal möchten wir eine andere Iteration (bzw. einen anderen Generator) in die gerade laufende Iteration einbinden. Dazu dienen die Keywords `yield from`. | Manchmal möchten wir eine andere Iteration (bzw. einen anderen Generator) in die gerade laufende Iteration einbinden. Dazu dienen die Keywords `yield from`. | ||
| Zeile 116: | Zeile 183: | ||
| Beispiel: ein einfacher Binärbaum besteht aus Knoten (_en_: Nodes), die jeweils bis zu zwei Kinder haben können. | Beispiel: ein einfacher Binärbaum besteht aus Knoten (_en_: Nodes), die jeweils bis zu zwei Kinder haben können. | ||
| - | {{:talit: | + | [[https:// |
| Um den Baum zu traversieren (d.h. alle Knoten zu besuchen), können wir zum Beispiel die [[wpde> | Um den Baum zu traversieren (d.h. alle Knoten zu besuchen), können wir zum Beispiel die [[wpde> | ||
| Zeile 122: | Zeile 189: | ||
| Eine rekursive Umsetzung könnte wie folgt aussehen - beachte, wie `yield from` eingesetzt wird, um die rekursive Traversierung zu erreichen. | Eine rekursive Umsetzung könnte wie folgt aussehen - beachte, wie `yield from` eingesetzt wird, um die rekursive Traversierung zu erreichen. | ||
| - | < | + | < |
| - | "></ | + | |
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | |||
| + | tree = Node(5, Node(2, Node(1), Node(3)), Node(7)) | ||
| + | for node in tree.in_order_traversal(): | ||
| + | </ | ||
| ### Aufgabe 4: Pre-Order Traversierung | ### Aufgabe 4: Pre-Order Traversierung | ||
| - | Füge eine Methode `pre_order_traveral` hinzu, die zuerst jeweils den Knoten selbst, dann den linken und rechten Teilbaum besucht. Die Reihenfolge des Besuchs sollte also `5 1 7` ausgeben. | + | Füge eine Methode `pre_order_traversal` hinzu, die zuerst jeweils den Knoten selbst, dann den linken und rechten Teilbaum besucht. Die Reihenfolge des Besuchs sollte also `5 2 1 3 7` ausgeben. |
| ### Weiter? | ### Weiter? | ||
| Zurück zum [[talit: | Zurück zum [[talit: | ||