Lambda-Funktionen in Python
Lerne Lambda-Funktionen in Python: anonyme Funktionen, Einsatz mit sorted(), map(), filter() und reduce().
Lambda-Funktionen in Python
Lambda-Funktionen sind kurze, anonyme Funktionen, die du in einer einzigen Zeile schreiben kannst. Sie sind ein maechniges Werkzeug, das deinen Code kompakter und eleganter machen kann - wenn du sie richtig einsetzt. In diesem Tutorial lernst du alles ueber Lambda-Funktionen und ihre praktischen Einsatzgebiete.
Was sind Lambda-Funktionen?
Eine Lambda-Funktion (auch anonyme Funktion genannt) ist eine Funktion ohne Namen. Sie wird mit dem Schluesselwort lambda erstellt und kann nur einen einzigen Ausdruck enthalten.
# Normale Funktion
def verdopple(x):
return x * 2
# Dasselbe als Lambda
verdopple_lambda = lambda x: x * 2
print(verdopple(5)) # Ausgabe: 10
print(verdopple_lambda(5)) # Ausgabe: 10
Warum “anonym”? Weil Lambda-Funktionen keinen eigenen Namen haben. Im Beispiel oben haben wir die Lambda-Funktion zwar einer Variable zugewiesen, aber das ist eigentlich nicht der typische Einsatz. Lambdas werden am haeufigsten direkt als Argument an andere Funktionen uebergeben.
Die Syntax
Die Syntax ist bewusst minimal:
lambda parameter: ausdruck
lambda- das Schluesselwortparameter- ein oder mehrere Parameter (durch Komma getrennt):- trennt Parameter vom Ausdruckausdruck- ein einzelner Ausdruck, dessen Ergebnis zurueckgegeben wird
# Keine Parameter
sage_hallo = lambda: "Hallo, Welt!"
print(sage_hallo()) # Ausgabe: Hallo, Welt!
# Ein Parameter
quadrat = lambda x: x ** 2
print(quadrat(4)) # Ausgabe: 16
# Mehrere Parameter
addiere = lambda a, b: a + b
print(addiere(3, 5)) # Ausgabe: 8
# Mit Standardwert
begruessung = lambda name, gruss="Hallo": f"{gruss}, {name}!"
print(begruessung("Anna")) # Ausgabe: Hallo, Anna!
print(begruessung("Max", "Hi")) # Ausgabe: Hi, Max!
# Mit Bedingung (ternärer Operator)
absolut = lambda x: x if x >= 0 else -x
print(absolut(-7)) # Ausgabe: 7
print(absolut(3)) # Ausgabe: 3
Wichtig: Ein Lambda darf nur einen einzigen Ausdruck enthalten - keine Schleifen, keine if-elif-else-Bloecke, keine Zuweisungen, kein print als Anweisung (nur als Ausdruck).
Lambda vs. def
Wann verwendest du was? Hier ein direkter Vergleich:
# --- def: Mehrzeilig, benannt, mit Docstring ---
def berechne_rabatt(preis, prozent):
"""Berechnet den rabattprierten Preis."""
rabatt = preis * prozent / 100
return preis - rabatt
# --- lambda: Einzeilig, anonym, ohne Docstring ---
berechne_rabatt_l = lambda preis, prozent: preis - (preis * prozent / 100)
| Eigenschaft | def | lambda |
|---|---|---|
| Name | Ja | Nein (anonym) |
| Mehrere Zeilen | Ja | Nein (nur ein Ausdruck) |
| Docstring | Ja | Nein |
| return-Anweisung | Explizit | Implizit (automatisch) |
| Lesbarkeit | Besser bei Komplexitaet | Besser bei Einfachheit |
| Typischer Einsatz | Wiederverwendbare Logik | Einmalige, kurze Operationen |
Einsatz mit sorted() und dem key-Parameter
Der haeufigste Einsatz von Lambda-Funktionen ist als key-Parameter bei Sortierfunktionen:
# Liste von Namen sortieren (Standard: alphabetisch)
namen = ["Zebra", "anna", "Max", "bob"]
print(sorted(namen))
# ['Max', 'Zebra', 'anna', 'bob'] (Grossbuchstaben vor Kleinbuchstaben)
# Case-insensitive Sortierung mit Lambda
print(sorted(namen, key=lambda name: name.lower()))
# ['anna', 'bob', 'Max', 'Zebra']
Tuples und Dictionaries sortieren
# Schueler nach Note sortieren
schueler = [
("Anna", 1.3),
("Max", 2.7),
("Lisa", 1.0),
("Tom", 3.3),
]
# Nach Note sortieren (zweites Element)
nach_note = sorted(schueler, key=lambda s: s[1])
print(nach_note)
# [('Lisa', 1.0), ('Anna', 1.3), ('Max', 2.7), ('Tom', 3.3)]
# Absteigend sortieren
nach_note_abst = sorted(schueler, key=lambda s: s[1], reverse=True)
print(nach_note_abst)
# [('Tom', 3.3), ('Max', 2.7), ('Anna', 1.3), ('Lisa', 1.0)]
# Dictionaries sortieren
produkte = [
{"name": "Laptop", "preis": 999},
{"name": "Maus", "preis": 29},
{"name": "Tastatur", "preis": 79},
{"name": "Monitor", "preis": 349},
]
# Nach Preis sortieren
nach_preis = sorted(produkte, key=lambda p: p["preis"])
for p in nach_preis:
print(f" {p['name']:>10}: {p['preis']:>6} Euro")
# Ausgabe:
# Maus: 29 Euro
# Tastatur: 79 Euro
# Monitor: 349 Euro
# Laptop: 999 Euro
# Nach Namenlaenge sortieren
nach_laenge = sorted(produkte, key=lambda p: len(p["name"]))
for p in nach_laenge:
print(f" {p['name']}")
# Ausgabe:
# Maus
# Laptop
# Monitor
# Tastatur
Mehrfache Sortierkriterien
mitarbeiter = [
{"name": "Anna", "abteilung": "IT", "gehalt": 55000},
{"name": "Max", "abteilung": "HR", "gehalt": 48000},
{"name": "Lisa", "abteilung": "IT", "gehalt": 62000},
{"name": "Tom", "abteilung": "HR", "gehalt": 51000},
{"name": "Sara", "abteilung": "IT", "gehalt": 55000},
]
# Erst nach Abteilung, dann nach Gehalt (absteigend)
sortiert = sorted(mitarbeiter, key=lambda m: (m["abteilung"], -m["gehalt"]))
for m in sortiert:
print(f" {m['abteilung']:>3} | {m['name']:<6} | {m['gehalt']} Euro")
# Ausgabe:
# HR | Max | 48000 Euro
# HR | Tom | 51000 Euro
# IT | Lisa | 62000 Euro
# IT | Anna | 55000 Euro
# IT | Sara | 55000 Euro
Einsatz mit map()
map() wendet eine Funktion auf jedes Element einer Sequenz an:
# Alle Zahlen verdoppeln
zahlen = [1, 2, 3, 4, 5]
verdoppelt = list(map(lambda x: x * 2, zahlen))
print(verdoppelt) # [2, 4, 6, 8, 10]
# Temperaturen umrechnen: Celsius -> Fahrenheit
celsius = [0, 20, 37, 100]
fahrenheit = list(map(lambda c: round(c * 9/5 + 32, 1), celsius))
print(fahrenheit) # [32.0, 68.0, 98.6, 212.0]
# Strings formatieren
namen = ["anna mueller", "max schmidt", "lisa weber"]
formatiert = list(map(lambda n: n.title(), namen))
print(formatiert) # ['Anna Mueller', 'Max Schmidt', 'Lisa Weber']
map() mit mehreren Sequenzen:
# Zwei Listen elementweise addieren
a = [1, 2, 3]
b = [10, 20, 30]
summen = list(map(lambda x, y: x + y, a, b))
print(summen) # [11, 22, 33]
# Punkte formatieren
x_werte = [1, 2, 3]
y_werte = [4, 5, 6]
punkte = list(map(lambda x, y: f"({x}, {y})", x_werte, y_werte))
print(punkte) # ['(1, 4)', '(2, 5)', '(3, 6)']
Hinweis: In modernem Python werden oft List Comprehensions statt map() bevorzugt:
# map() mit Lambda
verdoppelt = list(map(lambda x: x * 2, zahlen))
# List Comprehension (oft lesbarer)
verdoppelt = [x * 2 for x in zahlen]
Einsatz mit filter()
filter() filtert Elemente, fuer die die Funktion True zurueckgibt:
# Gerade Zahlen filtern
zahlen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
gerade = list(filter(lambda x: x % 2 == 0, zahlen))
print(gerade) # [2, 4, 6, 8, 10]
# Negative Zahlen entfernen
werte = [-5, 3, -1, 7, -3, 2, 8]
positiv = list(filter(lambda x: x > 0, werte))
print(positiv) # [3, 7, 2, 8]
# Leere Strings herausfiltern
woerter = ["Hallo", "", "Welt", "", "Python", ""]
nicht_leer = list(filter(lambda s: s, woerter))
print(nicht_leer) # ['Hallo', 'Welt', 'Python']
Praxis-Beispiel mit Dictionaries:
produkte = [
{"name": "Laptop", "preis": 999, "auf_lager": True},
{"name": "Maus", "preis": 29, "auf_lager": False},
{"name": "Tastatur", "preis": 79, "auf_lager": True},
{"name": "Monitor", "preis": 349, "auf_lager": True},
{"name": "Kabel", "preis": 12, "auf_lager": False},
]
# Nur Produkte auf Lager
auf_lager = list(filter(lambda p: p["auf_lager"], produkte))
print([p["name"] for p in auf_lager])
# ['Laptop', 'Tastatur', 'Monitor']
# Guenstige Produkte auf Lager (unter 100 Euro)
guenstig_und_da = list(filter(
lambda p: p["auf_lager"] and p["preis"] < 100,
produkte
))
print([p["name"] for p in guenstig_und_da])
# ['Tastatur']
Auch hier ist die List-Comprehension-Alternative oft lesbarer:
# filter() mit Lambda
gerade = list(filter(lambda x: x % 2 == 0, zahlen))
# List Comprehension
gerade = [x for x in zahlen if x % 2 == 0]
Einsatz mit reduce() (functools)
reduce() reduziert eine Sequenz auf einen einzelnen Wert, indem es die Funktion kumulativ anwendet. Du musst es aus functools importieren:
from functools import reduce
# Summe aller Zahlen (wie sum(), aber manuell)
zahlen = [1, 2, 3, 4, 5]
summe = reduce(lambda a, b: a + b, zahlen)
print(summe) # 15
# So funktioniert es Schritt fuer Schritt:
# Schritt 1: a=1, b=2 -> 3
# Schritt 2: a=3, b=3 -> 6
# Schritt 3: a=6, b=4 -> 10
# Schritt 4: a=10, b=5 -> 15
Weitere Beispiele:
from functools import reduce
# Produkt aller Zahlen
zahlen = [1, 2, 3, 4, 5]
produkt = reduce(lambda a, b: a * b, zahlen)
print(produkt) # 120 (1*2*3*4*5)
# Maximum finden (wie max(), aber manuell)
groesste = reduce(lambda a, b: a if a > b else b, zahlen)
print(groesste) # 5
# Strings zusammenfuegen
woerter = ["Python", "ist", "toll"]
satz = reduce(lambda a, b: f"{a} {b}", woerter)
print(satz) # "Python ist toll"
# Verschachtelte Listen flach machen
verschachtelt = [[1, 2], [3, 4], [5, 6]]
flach = reduce(lambda a, b: a + b, verschachtelt)
print(flach) # [1, 2, 3, 4, 5, 6]
Mit Startwert:
from functools import reduce
# Summe mit Startwert 100
zahlen = [1, 2, 3, 4, 5]
summe = reduce(lambda a, b: a + b, zahlen, 100)
print(summe) # 115 (100 + 1 + 2 + 3 + 4 + 5)
# Haeufigkeiten zaehlen
buchstaben = ["a", "b", "a", "c", "b", "a"]
haeufigkeit = reduce(
lambda d, b: {**d, b: d.get(b, 0) + 1},
buchstaben,
{}
)
print(haeufigkeit) # {'a': 3, 'b': 2, 'c': 1}
Wann Lambda, wann def?
Lambda verwenden wenn:
- Die Funktion sehr kurz ist (ein Ausdruck)
- Die Funktion nur einmal verwendet wird
- Sie als Argument an eine andere Funktion uebergeben wird
- Der Ausdruck selbsterklaerend ist
# GUT: Einfacher Sortier-Key
sorted(namen, key=lambda n: n.lower())
# GUT: Einfache Transformation
list(map(lambda x: x ** 2, zahlen))
# GUT: Einfacher Filter
list(filter(lambda x: x > 0, zahlen))
def verwenden wenn:
- Die Funktion mehrfach verwendet wird
- Die Logik komplex ist
- Du einen Docstring brauchst
- Die Funktion mehrere Anweisungen enthaelt
- Ein aussagekraeftiger Name die Lesbarkeit verbessert
# SCHLECHT: Lambda zu komplex
ergebnis = sorted(daten, key=lambda x: (
x["kategorie"],
-x["prioritaet"],
x["datum"].year,
x["name"].lower()
))
# BESSER: Benannte Funktion
def sortier_schluessel(eintrag):
"""Sortiert nach Kategorie, Prioritaet (absteigend), Jahr und Name."""
return (
eintrag["kategorie"],
-eintrag["prioritaet"],
eintrag["datum"].year,
eintrag["name"].lower()
)
ergebnis = sorted(daten, key=sortier_schluessel)
Lesbarkeit: Lambda nicht uebertreiben
Lambda-Funktionen koennen den Code unleserlich machen, wenn sie zu komplex werden. Hier einige Gegenueberstellungen:
# SCHLECHT: Verschachtelte Lambdas - kaum lesbar
ergebnis = list(map(lambda x: (lambda y: y ** 2)(x + 1), [1, 2, 3]))
# GUT: Klar und verstaendlich
def quadrat_plus_eins(x):
return (x + 1) ** 2
ergebnis = [quadrat_plus_eins(x) for x in [1, 2, 3]]
# SCHLECHT: Zu viel in einem Lambda
transformiert = list(map(
lambda s: s.strip().lower().replace(" ", "_") if isinstance(s, str) else str(s),
daten
))
# GUT: Ausgelagert mit klarem Namen
def normalisiere(wert):
"""Normalisiert einen Wert zu einem einheitlichen String-Format."""
if isinstance(wert, str):
return wert.strip().lower().replace(" ", "_")
return str(wert)
transformiert = [normalisiere(w) for w in daten]
Praxis-Beispiele
Beispiel 1: Datenverarbeitung mit Lambda-Pipeline
# Verkaufsdaten verarbeiten
verkaufsdaten = [
{"produkt": "Laptop", "menge": 5, "einzelpreis": 999.99},
{"produkt": "Maus", "menge": 50, "einzelpreis": 29.99},
{"produkt": "Monitor", "menge": 12, "einzelpreis": 349.99},
{"produkt": "Tastatur", "menge": 30, "einzelpreis": 79.99},
{"produkt": "Kabel", "menge": 100, "einzelpreis": 9.99},
]
# Gesamtpreis berechnen
mit_gesamt = list(map(
lambda v: {**v, "gesamt": round(v["menge"] * v["einzelpreis"], 2)},
verkaufsdaten
))
# Nur Verkaeufe ueber 1000 Euro
grosse_verkaeufe = list(filter(
lambda v: v["gesamt"] > 1000,
mit_gesamt
))
# Nach Gesamtpreis sortieren (absteigend)
sortiert = sorted(grosse_verkaeufe, key=lambda v: v["gesamt"], reverse=True)
print("Grosse Verkaeufe:")
for v in sortiert:
print(f" {v['produkt']:>10}: {v['gesamt']:>10.2f} Euro")
# Ausgabe:
# Laptop: 4999.95 Euro
# Monitor: 4199.88 Euro
# Tastatur: 2399.70 Euro
# Maus: 1499.50 Euro
Beispiel 2: Sortierung mit komplexen Kriterien
# Schachturnier-Ergebnisse
spieler = [
{"name": "Anna", "siege": 7, "remis": 2, "niederlagen": 1},
{"name": "Max", "siege": 6, "remis": 3, "niederlagen": 1},
{"name": "Lisa", "siege": 7, "remis": 1, "niederlagen": 2},
{"name": "Tom", "siege": 5, "remis": 4, "niederlagen": 1},
]
# Punkte: Sieg = 1, Remis = 0.5, Niederlage = 0
# Bei Gleichstand: Mehr Siege zuerst
rangliste = sorted(
spieler,
key=lambda s: (s["siege"] + s["remis"] * 0.5, s["siege"]),
reverse=True
)
print("Rangliste:")
for i, s in enumerate(rangliste, 1):
punkte = s["siege"] + s["remis"] * 0.5
print(f" {i}. {s['name']:<6} - {punkte} Punkte ({s['siege']}S/{s['remis']}R/{s['niederlagen']}N)")
Beispiel 3: Funktionale Datenverarbeitung
from functools import reduce
# Notenberechnung
noten = {
"Mathe": [2.0, 1.7, 2.3, 1.0],
"Deutsch": [1.3, 2.0, 1.7],
"Englisch": [1.0, 1.3, 1.0, 1.7],
"Physik": [3.0, 2.7, 2.3],
}
# Durchschnitt pro Fach
durchschnitte = {
fach: round(reduce(lambda a, b: a + b, n) / len(n), 2)
for fach, n in noten.items()
}
print("Durchschnitte pro Fach:")
for fach, schnitt in sorted(durchschnitte.items(), key=lambda x: x[1]):
print(f" {fach:<10}: {schnitt}")
# Gesamtdurchschnitt
gesamt = round(
reduce(lambda a, b: a + b, durchschnitte.values()) / len(durchschnitte),
2
)
print(f"\nGesamtdurchschnitt: {gesamt}")
# Bestes Fach
bestes = min(durchschnitte.items(), key=lambda x: x[1])
print(f"Bestes Fach: {bestes[0]} ({bestes[1]})")
Uebungen
Uebung 1: Sortierung
Sortiere die folgende Liste von Tupeln nach dem zweiten Element absteigend:
daten = [(1, "c", 30), (2, "a", 10), (3, "b", 20), (4, "d", 40)]
# Loesung
sortiert = sorted(daten, key=lambda x: x[2], reverse=True)
print(sortiert)
# [(4, 'd', 40), (1, 'c', 30), (3, 'b', 20), (2, 'a', 10)]
Uebung 2: Daten filtern und transformieren
Filtere aus einer Liste von Woertern alle mit mehr als 5 Buchstaben und wandle sie in Grossbuchstaben um:
woerter = ["Hund", "Elefant", "Katze", "Schmetterling", "Aal", "Giraffe", "Hai"]
# Loesung
ergebnis = list(map(
lambda w: w.upper(),
filter(lambda w: len(w) > 5, woerter)
))
print(ergebnis) # ['ELEFANT', 'SCHMETTERLING', 'GIRAFFE']
# Zum Vergleich: Als List Comprehension
ergebnis_lc = [w.upper() for w in woerter if len(w) > 5]
print(ergebnis_lc) # ['ELEFANT', 'SCHMETTERLING', 'GIRAFFE']
Uebung 3: Eigene min_by-Funktion
Schreibe eine Funktion, die das Minimum einer Liste basierend auf einer Lambda-Funktion findet:
def min_by(liste, schluessel):
"""Findet das Element mit dem kleinsten Schluesselwert."""
return reduce(
lambda a, b: a if schluessel(a) <= schluessel(b) else b,
liste
)
# Test
from functools import reduce
personen = [
{"name": "Anna", "alter": 28},
{"name": "Max", "alter": 22},
{"name": "Lisa", "alter": 35},
]
juengste = min_by(personen, lambda p: p["alter"])
print(juengste) # {'name': 'Max', 'alter': 22}
woerter = ["Elefant", "Aal", "Katze", "Hund"]
kuerzestes = min_by(woerter, lambda w: len(w))
print(kuerzestes) # Aal
Uebung 4: Funktions-Komposition
Erstelle eine Funktion, die mehrere Lambdas hintereinander ausfuehrt:
from functools import reduce
def komponiere(*funktionen):
"""Komponiert mehrere Funktionen zu einer einzigen.
komponiere(f, g, h)(x) entspricht f(g(h(x)))
"""
return reduce(
lambda f, g: lambda x: f(g(x)),
funktionen
)
# Test
verdopple = lambda x: x * 2
plus_drei = lambda x: x + 3
quadriere = lambda x: x ** 2
# Erst quadrieren, dann plus 3, dann verdoppeln
transformation = komponiere(verdopple, plus_drei, quadriere)
print(transformation(4)) # verdopple(plus_drei(quadriere(4))) = verdopple(plus_drei(16)) = verdopple(19) = 38
# String-Verarbeitung
bereinige = komponiere(
lambda s: s.strip(),
lambda s: s.lower(),
lambda s: s.replace(" ", " ")
)
print(bereinige(" Hallo WELT ")) # "hallo welt"
Pro-Tipp: Lambda oder List Comprehension?
In der Python-Community gibt es eine klare Tendenz: List Comprehensions werden gegenueber map() und filter() mit Lambda bevorzugt, weil sie als “pythonischer” gelten. Beide Varianten sind aber voellig valide.
# Lambda + map/filter
ergebnis = list(map(lambda x: x ** 2, filter(lambda x: x > 0, zahlen)))
# List Comprehension (bevorzugt)
ergebnis = [x ** 2 for x in zahlen if x > 0]
Lambda glaenzt aber dort, wo keine List Comprehension moeglich ist: beim key-Parameter von sorted(), min(), max() und aehnlichen Funktionen. Dort ist Lambda das Mittel der Wahl und voellig idiomatisch.