Python *args und **kwargs
Lerne, wie *args und **kwargs Python-Funktionen ermöglichen, beliebig viele positions- und schlüsselwortbasierte Argumente zu akzeptieren.
*args und **kwargs sind eine spezielle Syntax in Python, die es einer Funktion ermöglicht, eine variable Anzahl von Argumenten zu akzeptieren. *args sammelt zusätzliche positionelle Argumente in einem Tuple, während **kwargs zusätzliche Schlüsselwortargumente in einem Dictionary sammelt. Zusammen bieten sie vollständige Flexibilität — man kann Funktionen schreiben, die mit einem oder hundert Argumenten funktionieren.
Diese Seite behandelt beide Funktionen ausführlich: wie sie funktionieren, wann man sie einsetzt, wie man sie kombiniert und welche häufigen Fallstricke zu vermeiden sind.
Was ist *args?
Wenn man einem Parameternamen einen einzelnen Stern (*) voranstellt, sammelt Python alle zusätzlichen positionellen Argumente, die an die Funktion übergeben werden, in einem Tuple, das an diesen Parameternamen gebunden wird. Der Name args ist eine Konvention — man könnte auch *numbers oder *values schreiben — aber *args ist allgemein bekannt.
def add_all(*args):
total = 0
for n in args:
total += n
return total
print(add_all(1, 2, 3)) # 6
print(add_all(10, 20, 30, 40)) # 100
print(add_all()) # 0Innerhalb der Funktion ist args ein gewöhnliches Tuple, über das man iterieren, auf das man zugreifen oder das man an andere Funktionen weitergeben kann. Der Aufruf von add_all() ohne Argumente ist gültig — args ist einfach ein leeres Tuple.
Reguläre Parameter mit *args kombinieren
Reguläre (positionelle) Parameter kommen zuerst; *args fängt alles auf, was danach folgt:
def greet(greeting, *names):
for name in names:
print(greeting + ', ' + name + '!')
greet('Hello', 'Alice', 'Bob', 'Charlie')
# Hello, Alice!
# Hello, Bob!
# Hello, Charlie!greeting wird durch das erste Argument befüllt; names erhält den Rest als Tuple. Wenn man greet('Hi') ohne weitere Namen aufruft, ist names ein leeres Tuple und die Schleife wird einfach nicht ausgeführt — kein Fehler.
Was ist **kwargs?
Zwei Sterne (**) vor einem Parameternamen weisen Python an, alle zusätzlichen Schlüsselwortargumente in einem Dictionary zu sammeln. Auch hier ist kwargs nur eine Konvention; jeder gültige Python-Bezeichner funktioniert.
def describe(**kwargs):
for key, value in kwargs.items():
print(key + ': ' + str(value))
describe(name='Alice', age=30, city='New York')
# name: Alice
# age: 30
# city: New YorkInnerhalb der Funktion ist kwargs ein gewöhnliches Dictionary. Man kann darüber iterieren, Schlüssel nachschlagen oder es weitergeben. Der Aufrufer entscheidet, welche Schlüssel angegeben werden — keiner von ihnen ist durch die Funktionsdefinition festgelegt.
Wann man **kwargs einsetzt
**kwargs glänzt, wenn:
- Eine Funktion eine flexible, offene Menge benannter Optionen akzeptieren soll (Konfiguration, Metadaten, HTML-Attribute).
- Man einen Wrapper schreibt, der Schlüsselwortargumente an eine andere Funktion weiterleiten muss, ohne zu wissen, welche das sind.
- Man ein Dictionary aus Schlüsselwortargumenten auf lesbare Weise aufbauen möchte (vermeidet den Boilerplate-Code von
dict(key=value, ...)).
*args und **kwargs kombinieren
Eine einzelne Funktion kann unbegrenzt viele positionelle und unbegrenzt viele Schlüsselwortargumente akzeptieren. Die erforderliche Reihenfolge in der Signatur ist:
- Normale positionelle Parameter
*args- Nur-Schlüsselwort-Parameter (mit Standardwerten)
**kwargs
def log_event(event, *tags, **metadata):
print('Event:', event)
print('Tags:', tags)
print('Metadata:', metadata)
log_event('login', 'auth', 'user', user_id=42, ip='127.0.0.1')
# Event: login
# Tags: ('auth', 'user')
# Metadata: {'user_id': 42, 'ip': '127.0.0.1'}event nimmt das erste positionelle Argument; tags fängt die restlichen positionellen Argumente auf; metadata fängt alle Schlüsselwortargumente auf.
Argumente mit * und ** entpacken
Die Operatoren * und ** sind nicht nur für Funktions-definitionen — sie funktionieren auch auf der Aufruf-Seite, um Sequenzen und Mappings in einzelne Argumente zu entpacken.
Eine Liste oder ein Tuple mit * entpacken
def multiply(a, b, c):
return a * b * c
nums = [2, 3, 4]
print(multiply(*nums)) # 24*nums entpackt die Liste so, dass a=2, b=3, c=4. Dies entspricht dem Schreiben von multiply(2, 3, 4). Weitere Informationen zum Entpackungsoperator findest du unter Unpack Tuples.
Ein Dictionary mit ** entpacken
def power(base, exp):
return base ** exp
params = {'base': 3, 'exp': 4}
print(power(**params)) # 81**params ordnet jeden Dictionary-Schlüssel dem entsprechenden Parameternamen zu. Dies ist nützlich, wenn Argumente in einem zur Laufzeit erstellten Konfigurations-Dictionary gespeichert sind.
Nur-Schlüsselwort-Argumente nach *args
Jeder Parameter, der in der Signatur nach *args aufgeführt wird, kann nur namentlich übergeben werden (er wird zu einem Nur-Schlüsselwort-Argument). Dies ist eine saubere Möglichkeit, optionale Flags ohne Mehrdeutigkeit hinzuzufügen:
def configure(host, *args, port=80, debug=False):
print('host:', host)
print('extra:', args)
print('port:', port)
print('debug:', debug)
configure('localhost', 'arg1', port=8080, debug=True)
# host: localhost
# extra: ('arg1',)
# port: 8080
# debug: Trueport und debug können nicht positionell gesetzt werden, da *args bereits alle positionellen Überschüsse verbraucht. Dieses Muster ist in Bibliotheks-APIs üblich — Benutzer müssen port=8080 explizit schreiben, was Aufrufstellen selbstdokumentierend macht.
Eine ausführliche Erklärung der Scoping-Regeln in Python findest du unter Python Scope.
Argumente an eine andere Funktion weiterleiten
Eine der praktischsten Verwendungen von *args/**kwargs ist das Schreiben von Wrappern und Dekoratoren, die Argumente an eine innere Funktion weiterleiten, ohne zu wissen, welche das sind:
def add_all(*args):
return sum(args)
def wrapper(*args, **kwargs):
print('Calling with args:', args, 'kwargs:', kwargs)
return add_all(*args)
print(wrapper(1, 2, 3))
# Calling with args: (1, 2, 3) kwargs: {}
# 6Dieses Muster findet sich in der gesamten Standardbibliothek von Python und ist die Grundlage von Dekoratoren und Funktionen höherer Ordnung.
Vollständige Signatur-Reihenfolge
Python erzwingt eine strikte Reihenfolgeregel für alle Parameterarten. Die vollständige Reihenfolge ist:
| Position | Art | Beispiel |
|---|---|---|
| 1 | Nur-positionell (Python 3.8+) | a, b, / |
| 2 | Normal positionell-oder-Schlüsselwort | x, y |
| 3 | Variable positionell | *args |
| 4 | Nur-Schlüsselwort | flag=True |
| 5 | Variable Schlüsselwort | **kwargs |
Das Verletzen dieser Reihenfolge führt zu einem SyntaxError. Eine Funktion, die alle fünf Arten verwendet, sieht so aus:
def full_sig(pos1, pos2, /, normal, *args, kw_only, **kwargs):
print(pos1, pos2, normal, args, kw_only, kwargs)
full_sig(1, 2, 3, 4, 5, kw_only='k', extra='e')
# 1 2 3 (4, 5) k {'extra': 'e'}Im alltäglichen Code braucht man selten alle fünf gleichzeitig. Die häufigsten Muster sind *args allein, **kwargs allein oder *args gefolgt von **kwargs.
Typannotationen
Man kann *args und **kwargs mit Typhinweisen annotieren. Die Annotation gilt für jedes einzelne Element, nicht für das Tuple oder Dictionary selbst:
from typing import Any
def add_all(*args: float) -> float:
return sum(args)
def describe(**kwargs: Any) -> None:
for key, value in kwargs.items():
print(f'{key}: {value}')
print(add_all(1.5, 2.5, 3.0)) # 7.0
describe(name='Bob', score=99)
# name: Bob
# score: 99*args: float bedeutet, dass jedes Element von args ein float sein soll. **kwargs: Any bedeutet, dass Werte beliebig sein können. Dies hält statische Analysetools zufrieden und bewahrt gleichzeitig die Flexibilität zur Laufzeit.
Häufige Fallstricke
1. Falsche Argumentreihenfolge in der Signatur
Das Platzieren von **kwargs vor *args ist ein SyntaxError:
# Wrong — raises SyntaxError
# def bad(name, **kwargs, *args): ...
# Correct
def good(name, *args, **kwargs):
pass2. Das args-Tuple verändern
args ist ein Tuple und daher unveränderlich. Wenn man die Argumente ändern muss, sollte man zuerst in eine Liste umwandeln:
def double_all(*args):
items = list(args) # mutable copy
items = [x * 2 for x in items]
return items
print(double_all(1, 2, 3)) # [2, 4, 6]3. Einen erforderlichen Parameternamen überschatten
Wenn man *args verwendet und auch ein Schlüsselwortargument mit demselben Namen wie ein positioneller Parameter hat, können Aufrufer verwirrt werden. Parameternamen sollten eindeutig sein, und Nur-Schlüsselwort-Parameter (nach *args) sollten für optionale Flags verwendet werden.
4. **kwargs übermäßig statt expliziter Parameter verwenden
**kwargs verbirgt, was eine Funktion tatsächlich akzeptiert, und erschwert die Autovervollständigung und statische Analyse. Explizite Parameter sollten für die Optionen bevorzugt werden, die eine Funktion tatsächlich unterstützt; **kwargs sollte nur verwendet werden, wenn die Menge der Optionen wirklich offen ist oder wenn an eine andere Funktion weitergeleitet wird.
Zusammenfassung
| Funktion | Syntax | Was gesammelt wird | Typ innerhalb der Funktion |
|---|---|---|---|
| Variable positionelle Argumente | *args | Zusätzliche positionelle Argumente | tuple |
| Variable Schlüsselwortargumente | **kwargs | Zusätzliche Schlüsselwortargumente | dict |
| Sequenz beim Aufruf entpacken | func(*seq) | Liste/Tuple → positionelle Argumente | — |
| Mapping beim Aufruf entpacken | func(**mapping) | Dict → Schlüsselwortargumente | — |
Zu eng verwandten Themen siehe Python Functions für Grundlagen zu Funktionen, Python Lambda für anonyme Funktionen und Python Scope dafür, wie Python Variablennamen auflöst.