Open Source im professionellen Einsatz

Newsletter abonnieren
Seite durchsuchen

HEFTARCHIV | NEWS | E-BIBLIOTHEK | VIDEO | BLOGS | WHITEPAPER | EVENTS | ACADEMY | ABO | SHOP

user friendly

  Home  »  Online Artikel  »  Funktionale Programmierung (2): Python funktional  

RSS-Feed der aktuellen News von Linux-Magazin Online Folgen Sie Linux-Magazin Online auf Twitter
Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark

Generatoren

Charakteristisch für funktionale Programmiersprachen ist auch das Verarbeiten von (unendlichen) Listen. Generatoren lassen Listen leicht entstehen, da mit ihnen einfach Iteratoren über Listen erzeugt werden können. In Python ist ein Objekt dann ein Iterator, wenn er das Iteratorprotokoll umsetzt. Das Iteratorprotokoll setzt ein Objekt dann um, wenn es die Methoden "__iter__" und "next" anbietet. Während "__iter__" eine interne Methode ist, können mit "next" die Elemente des Iterators angefordert werden. Obwohl Python Generatoren seit Version 2.3 unterstützt, sind sie doch relativ unbekannt. Da Generatoren nicht nur Werte produzieren, sondern auch konsumieren können, lassen sich mit ihnen Koroutinen implementieren. Eine mächtige Verknüpfung von List Comprehension und Generatoren stellen Generator-Ausdrücke dar.

Aber nun erst einmal zu Generatoren als reine Produzenten. Der einfache Generator aus Abbildung 5 gibt auf Anfrage alle natürliche Zahlen aus.


Abbildung 5: Generator für die natürlichen Zahlen.

Von der Praxis zur Theorie: Durch das Schlüsselwort "yield" wird die Funktion zu einem Generator. Die Werte des Generators lassen sich implizit durch eine Iteration über den Generator oder explizit mit der Funktion "next" anfordern. Wird beim Prozessieren der Funktion die Anweisung "yield" erreicht, wird die Ausführung der Generators einerseits eingefroren und andererseits der Wert von "yield" zurückgegeben. Die Iteration über die Werte des Generators ist mit der Abarbeitung des Funktionskörpers oder einer expliziten Return-Anweisung beendet.

In Abbildung 6 ist schön zu sehen, dass ein Generator auch endlich viele Werte erzeugen kann und dass die "next"-Funktion in Iteratorkontexten wie "for i in generatePython(): print i," implizit aufgerufen wird.


Abbildung 6: Ein endlicher Generator.

Ab Python 2.5 können Generatoren nicht nur Werte produzieren, sondern auch konsumieren. Der Generator besitzt das folgende Interface:

  • next: produziere einen Wert
  • send: konsumiere einen Wert
  • close: schliesse den Generator

Der Generator wird zur Koroutine, denn er kann an einer beliebigen Stelle aufgerufen, verlassen oder beendet werden. Die Koroutine (Abbildung 7) unterscheidet sich nur unwesentlich zum Generator für die natürlichen Zahlen aus Abbildung 5. Durch "val= (yield i)" nimmt er Werte an, die mittels "send" an ihn geschickt werden. Falls der Generator einen neuen Wert erhält, wird in "if (val): i=val" der Rückgabewert des Generators neu gesetzt. "n.close" schliesst den Generator.


Abbildung 7: Der Generator wird zur Koroutine.

David Beazley zeigt in seinen englischsprachigen Präsentation "A Curious Course on Coroutines and Concurrency", dass sich Generatoren sogar zum Implementieren eines Multitasking-Betriebssystems einsetzen lassen.

Generator-Ausdrücke

Generator-Ausdrücke verbinden die Funktionalität von List Comprehension mit der Bedarfsauswertung von Generatoren. Ein Generator-Ausdruck unterscheidet sich von der List Comprehension syntaktisch dadurch, das er in runden Klammer definiert wird und semantisch dadurch von der List Comprehension, das er einen Generator zurückgibt. Dadurch wird gleichzeitig die Performance des Programms erhöht und Speicherplatz gespart, denn die Werte des Generator-Ausdrucks werden erst auf Anfrage erzeugt und im Speicher gehalten, und dies auch nur soweit wie nötig (Abbildung 8).


Abbildung 8: Die Werte des Generator-Ausdrucks werden erst auf Anfrage erzeugt.

Mit Generator-Ausdrücken lassen sich sehr mächtige Generatoren erzeugen, die Datenströme liefern - und das nur auf Anfrage. Dazu werden drei Komponenten benötigt: Die Funktion "generateOpenRange" (Listing 2) produziert natürliche Zahlen, beginnend mit "start" in "step"-Schritten. Ebenfalls notwendig ist ein Generatorausdruck, der die Daten aus "generateOpenRange" bearbeitet, und zuletzt noch die Funktion "takewhile" aus der Bibliothek "itertools", die nur soviele Elemente aus dem Generator-Ausdruck ausliest, wie angefordert werden.

Listing 2: Unendlicher Datenstrom

def generateOpenRange(start=1,step=1):
  i=start
  while True:
    yield i
    i+=step

Ein paar Beispiele in Abbildung 9 sollen dies verdeutlichen. Insbesondere zeigt das letzte Beispiel, wie sich mit "list" eine Bedarfsauswertung zur strikten Auswertung durch eine Liste transformieren lässt.


Abbildung 9: Datenströme.

Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark
Ähnliche Artikel
Funktionale Programmierung (3): Das MapReduce-Framework Funktionale Programmierung (3): Das MapReduce-Framework
Funktionale Programmierung (1): Grundzüge Funktionale Programmierung (1): Grundzüge
Objekterkennung Python-Skript erkennt Gesichter, Haut und Texte
Vernetzte Welten Das Globus-Toolkit, Version 2
Postverteilung Software zur Verwaltung von Verteilerlisten
Deko mit Nutzen Dekoratoren in Python
Whitepaper
Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele

Über die letzten Jahre hinweg haben sich Open Source Lösungen als fester Bestandteil des gesamten Datenintegrationsmarktes etabliert. Viele Unternehmen haben bereits das Open Source Modell für Ihre Datenintegrationsprojekte aufgegriffen. Das vorliegende White Paper illustriert anhand ausgewählter Fallstudien und Anwendungsbeispiele die Implementierung von Open Source Datenintegration in der Praxis und benennt die daraus resultierenden Vorteile.

Download PDF (Registrierung erforderlich)
The Role of Open Source in Data Integration

Obwohl in den letzten Jahren viele technische Fortschritte erzielt werden konnten, verfügen die meisten Datenintegrationsprozesse nach wie vor nur über eine sehr begrenzte Automatisierung. Das vorliegende White Paper von dem Industry Analyst Mark Madson wird zunächst ein grundlegendes Verständnis von Daten Integration vermitteln, die Vorzüge von Open Source Lösungen für Daten Integration erläutern und Ihnen professionelle Empfehlungen geben, damit Sie Ihre Integrationsjobs noch einfacher und produktiver gestalten können.

Download PDF (Registrierung erforderlich)
Kommentare (2)
von
Mathias Huber,
25.01.2010 17:31
Re: Kleiner Fehler in qSortFilter
Haben Sie herzlichen Dank für den Hinweis! Wir haben das Listing korrigiert.
von
hochmohr,
23.01.2010 19:52
Kleiner Fehler in qSortFilter
Zwei kleine Fehler haben sich eingeschlichen:

def qsortFilter(L):
if len(L) <= 1: return L
return qsortFilter( filter(lambda lt: lt < L[0] , L[1:]) ) + L[0:1] + qsortFilter( filter(lambda gt: gt >= L[0] , L[1:]) )