Zip - der Reißverschluss
Ein häufiger Anwendungsfall besteht darin, eine Ausgabeliste durch Verknüpfung von Eingabelisten zu erzeugen. Dazu bietet sich die funktionale Built-In Funktion "zip" an. Sie erzeugt aus den Eingabelisten eine Ausgabeliste über Tupels, deren erste Tupel die ersten Elemente der Eingabelisten sind, deren zweites Tupel die zweiten Elemente der Eingabelisten sind und so fort. Ihre Länge entspricht der minimalen Länge der Eingabelisten.
Leider lässt sich "zip" nicht über eine Funktion parametrisieren. Hierzu kann man die Funktion "map" mit "None" als Abbildungsfunktion verwenden, aber die durch "map" erzeugte Liste besitzt die Eigenschaft, dass ihre Länge der maximalen Länge der Eingabeliste entspricht. Fehlende Elemente werden auf "None" gesetzt. Die Anwendung der anonymen-Funktion "lambda a,b,c: a+b+c" auf "None"-Argumente führt infolgedessen zu einem "TypeError" (Abbildung 12).

|
Abbildung 12: Verknüpfen von Eingabelisten mit "zip" und "map".
|
Die Funktion "zipWith" (Listing 6), die die Abbildungsfunktionalität von "map" und die Verknüpfungseigenschaften von "zip" besitzt, ist schnell implementiert. Noch ein paar Worte zu der Funktion "zipWith": Die minimale Länge über alle Listen wird durch den Ausdruck "min(map(len,args))" berechnet. Diese minimale Länge "minLength" wird in "map( lambda a : a[0:minLength],args )" verwendet, um neue Listen ("sliceArgs"), die diese Länge besitzen, zu erzeugen. Letztendlich wird die "map" Funktion über die verkürzten Eingabelisten angewandt.
|
Listing 6: Die Funktion zipWith
|
def zipWith( func, *args):
minLength= min(map(len,args))
sliceArgs= map( lambda a : a[0:minLength],args )
return map ( func, *sliceArgs )
|
Die Funktion "zipWith" ist wieder ein Beispiel dafür, wie aus einfachen funktionalen Bausteinen mächtige Funktionen (Abbildung 13) gebildet werden können.

|
Abbildung 13: Die Funktion "zipWith" angewandt.
|
Bibliotheken für das funktionale Programmieren
Die Bibliotheken "operator", "functools" und "itertools" runden das funktionale Programmieren in Python ab. "operator" enthält eine Menge von Funktionen als Operatoren, die das Verarbeiten von Sequenzen deutlich erleichtert. Die Operatoren werden dort gerne eingesetzt, wo normale oder auch anonyme Funktionen mehr Tipparbeit verlangen. Im folgenden Beispiel (Abbildung 14) werden zwei Listen zu einer neuen verknüpft. Da ein String in Python eine Sequenz von Zeichen (characters) darstellt, werden die Buchstabenpaare miteinander verglichen. Das Spektrum der "operator" Bibliothek reicht von Objektvergleichen über logische Operationen, mathematische Operationen und Sequenz-Operationen bis zu Typvergleichen. Wer es genauer wissen will, kann dies in der Operator-Dokumentation nachlesen.

|
Abbildung 14: Reguläre und anonyme Funktionen sowie Operatoren.
|
Die "functools"-Bibliothek enthält die Funktion "partial". Diese Funktion höherer Ordnung nimmt eine Funktion und optional deren Argumente an und gibt eine Funktion zurück, die diese Argumente bereits angewandt hat. Damit lässt sich die Funktion "myDivide" (Abbildung 15) über zwei Argumente, in zwei Funktionen über jeweils ein Argument transformieren. Der Aufruf "divide1By(3)" zeigt, das ein Aufrufargument explizit an das entsprechende Funktionsargument gebunden werden muss.

|
Abbildung 15: Partial Evaluation.
|
Die "itertools"-Bibliothek bietet einen reichen Satz an kleiner Helferlein an um aus einfachen Sequenzen mächtige Iteratoren zu bilden. Die Methoden "imap", "izip" und "ifilter" dieser Bibliothek sind die Lazy-Pendants zu den Python 2.* built-in Funktionen "map", "zip" und "filter" und ersetzen diese mit Python 3.*. Neben diesen Methoden, die die Elemente einer Sequenz verarbeiten, besitzt "itertools" viele Funktionen um Iteratoren über Sequenzen oder unendlichen Datenströmen zu erzeugen.
|
Iteratoren
|
|
Funktion
|
Beschreibung
|
|
count(n=0)
|
Datenstrom über die natürlichen Zahlen, beginnend bei n
|
|
cycle(seq)
|
unendliche Wiederholung der Sequenz
|
|
chain(seq1,seq2,..)
|
(endliche) Verkettung der Sequenzen
|
|
islice(seq,[start],stop[,end])
|
endlicher Slice von seq
|
|
tee(seq,n=2)
|
Vervielfältigung der Sequenz seq
|

|
Abbildung 16: Erzeugen von Iteratoren mit Itertools.
|
Mit Python 2.6 bietet die "itertools" Bibliothek die drei weiteren Funktionen "product", "permutations" und "combinations" an. Damit lassen sich bei vorgegebener Sequenz und k alle k-elementigen Teilmengen aus einer Sequenz bilden (Abbildung 17). Während "product" einen Iterator über alle k-elementigen Teilmengen erzeugt, erzeugt "permutations" nur Teilmengen, die sich nicht wiederholen. "combinations" stellt sicher, das die Teilmengen darüber hinaus sortiert sind.

|
Abbildung 17: Kombinationen über Sequenzen mit Itertools.
|
Die Dokumentation zur Itertools-Bibliothek enthält viele Rezepte rund um deren Anwendung.
| Whitepaper |
|
Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele (Folge 2)
Der zweite Teil des Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele White Papers beleuchtet anhand weiterer ausgewählter Case Studies die Implementierung von Open Source Datenintegration in der Praxis und benennt die daraus resultierenden Vorteile.
Download PDF (Registrierung erforderlich)
|
|
Usage Landscape Enterprise Open Source Data Integration
Die Nachfrage nach Datenintegrationslösungen für Unternehmen ist zunehmend gestiegen und vor allem das Interesse an Open Source Technologien wird immer größer. Doch wie und von wem werden Open Source Datenintegrationslösungen genutzt und welches Nutzungsverhalten lässt sich daraus ableiten? Das vorliegende White Paper präsentiert die Erfahrungswerte von über 1000 Open Source Nutzern und liefert fundierte Antworten auf diese Fragen.
Download PDF (Registrierung erforderlich)
|
Dieser Online-Artikel kann Links enthalten, die auf nicht mehr vorhandene Seiten verweisen. Wir ändern solche "broken links"
nur in wenigen Ausnahmefällen. Der Online-Artikel soll möglichst unverändert der gedrucken Fassung entsprechen.
|
Mathias Huber,
25.01.2010 17:31
hochmohr,
23.01.2010 19:52
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:]) )