*args und **kwargs: Flexible Funktionsargumente in Python
Wie du mit *args und **kwargs Funktionen schreibst, die beliebig viele Argumente annehmen – verständlich erklärt mit praktischen Beispielen.
Irgendwann stößt du beim Programmieren in Python auf Funktionsdefinitionen wie def funktion(*args, **kwargs) und fragst dich, was diese Sternchen eigentlich bedeuten. Keine Sorge – dahinter steckt ein einfaches, aber mächtiges Konzept: Mit *args und **kwargs kannst du Funktionen schreiben, die eine beliebige Anzahl von Argumenten entgegennehmen. In diesem Beitrag schauen wir uns Schritt für Schritt an, wie das funktioniert und wann du es einsetzt.
Das Problem: feste Anzahl an Parametern
Normalerweise definierst du genau, wie viele Argumente eine Funktion erwartet. Das funktioniert gut, solange du die Anzahl kennst:
def addiere(a, b):
return a + b
print(addiere(3, 5)) # 8
Aber was, wenn du nicht weißt, wie viele Zahlen addiert werden sollen? Mal sind es zwei, mal fünf, mal zehn. Du könntest eine Liste übergeben – oder du nutzt *args, um die Funktion flexibel zu machen.
*args: beliebig viele Positionsargumente
Mit einem einzelnen Sternchen vor einem Parameternamen sammelst du alle übergebenen Positionsargumente in einem Tupel. Der Name args ist dabei nur Konvention – das Sternchen ist entscheidend.
def addiere(*args):
summe = 0
for zahl in args:
summe += zahl
return summe
print(addiere(3, 5)) # 8
print(addiere(1, 2, 3, 4, 5)) # 15
print(addiere()) # 0
Innerhalb der Funktion ist args ein ganz normales Tupel, über das du iterieren kannst. Du kannst *args auch mit festen Parametern kombinieren – dann müssen die festen zuerst stehen:
def begruesse(begruessung, *namen):
for name in namen:
print(f"{begruessung}, {name}!")
begruesse("Hallo", "Anna", "Ben", "Carla")
# Hallo, Anna!
# Hallo, Ben!
# Hallo, Carla!
**kwargs: beliebig viele Schlüsselwortargumente
Zwei Sternchen sammeln dagegen alle benannten Argumente (Keyword-Argumente) in einem Dictionary. Auch hier ist der Name kwargs (für keyword arguments) nur eine Konvention.
def beschreibe(**kwargs):
for schluessel, wert in kwargs.items():
print(f"{schluessel}: {wert}")
beschreibe(name="Laptop", preis=999, marke="TechCo")
# name: Laptop
# preis: 999
# marke: TechCo
Das ist besonders nützlich, wenn eine Funktion optionale Einstellungen entgegennehmen soll, deren Namen du nicht alle fest vorgeben möchtest – etwa bei Konfigurationen oder beim Weiterreichen von Argumenten.
Beides kombinieren: die richtige Reihenfolge
Du kannst feste Parameter, *args und **kwargs gemeinsam verwenden. Dabei gilt eine feste Reihenfolge: erst die normalen Parameter, dann *args, dann **kwargs.
def funktion(pflicht, *args, **kwargs):
print("Pflicht:", pflicht)
print("Args:", args)
print("Kwargs:", kwargs)
funktion("A", 1, 2, 3, x=10, y=20)
# Pflicht: A
# Args: (1, 2, 3)
# Kwargs: {'x': 10, 'y': 20}
Hältst du diese Reihenfolge nicht ein, meldet Python einen SyntaxError. Merke dir einfach: zuerst das Konkrete, dann das Flexible.
Das Sternchen zum Entpacken nutzen
Spannend wird es, wenn du das Sternchen beim Aufruf einer Funktion einsetzt. Dann wirkt es genau umgekehrt: Es entpackt eine Liste oder ein Dictionary in einzelne Argumente. Das ist extrem praktisch, wenn deine Daten bereits in einer Sammlung liegen.
def punkt(x, y, z):
return f"({x}, {y}, {z})"
koordinaten = [1, 2, 3]
print(punkt(*koordinaten)) # (1, 2, 3) – Liste wird entpackt
einstellungen = {"x": 4, "y": 5, "z": 6}
print(punkt(**einstellungen)) # (4, 5, 6) – Dict wird entpackt
Eine sehr häufige Anwendung ist das Weiterreichen von Argumenten an eine andere Funktion, ohne sie einzeln aufzählen zu müssen – etwa in Decorators oder Wrapper-Funktionen:
def logge_aufruf(funktion):
def wrapper(*args, **kwargs):
print(f"Rufe {funktion.__name__} auf ...")
return funktion(*args, **kwargs)
return wrapper
@logge_aufruf
def multipliziere(a, b):
return a * b
print(multipliziere(4, 6))
# Rufe multipliziere auf ...
# 24
Hier nimmt der Wrapper mit *args, **kwargs alle Argumente entgegen und gibt sie unverändert weiter – egal wie die dekorierte Funktion aussieht.
Fazit
Mit *args und **kwargs schreibst du flexible Funktionen, die sich an unterschiedliche Aufrufe anpassen: *args sammelt Positionsargumente in einem Tupel, **kwargs benannte Argumente in einem Dictionary. Dieselben Sternchen entpacken beim Aufruf Listen und Dictionaries wieder in einzelne Argumente. Setze sie gezielt ein, wo echte Flexibilität gefragt ist – etwa bei Decorators oder Wrapper-Funktionen. Wo die Anzahl der Parameter dagegen klar ist, bleiben feste Parameter die lesbarere Wahl. Probier die Beispiele am besten direkt aus und tippe sie selbst ab – so verankert sich das Konzept am schnellsten.