*args — sammelt eine beliebige Anzahl von positionalen Argumenten in einem Tupel.
**kwargs — sammelt eine beliebige Anzahl von benannten Argumenten (schlüssel=wäre) in einem Wörterbuch.
Das ermöglicht das Schreiben von Funktionen mit flexiblem Interface:
def my_func(a, b, *args, **kwargs): print(a, b) print(args) print(kwargs) my_func(1, 2, 3, 4, x=10, y=20) # 1 2 # (3, 4) # {'x': 10, 'y': 20}
Feinheiten:
Kann man die Reihenfolge von *args und benannten Argumenten mit Standardwerten ändern, zum Beispiel:
def foo(a, *args, x=10, **kwargs): pass
oder muss man immer die Standardwerte nach *args setzen?
Antwort:
In Python 3 ist das möglich! So (in Python 2 hat es nicht funktioniert):
def foo(a, *args, x=10): pass
Parameter nach *args ("keyword-only arguments") können Standardwerte haben oder erforderlich sein — sie können nur nach Namen angegeben werden.
Geschichte
Falsche Übergabe von Argumenten über *args/**kwargs
In REST-API-Diensten wurde die Automatisierung des Marshallings von Daten über **kwargs aufgebaut. Ein überflüssiger Parameter wurde übersehen — die Funktion nahm unerwartete Werte in kwargs entgegen, was zu einem Verlust der Kontrolllogik und schwer zu debuggenden Fehlern führte.
Geschichte
Doppelte benannte Argumente
Beim Aufruf der Funktion gab der Entwickler versehentlich einen Parameter sowohl explizit als auch über **kwargs an, z.B.: my_func(a=1, **{"a": 2}). Dies führte zu einem TypeError und dem Zusammenbruch des Dienstes.
Geschichte
Positionale oder nur benannte Argumente vergessen
Bei der Erstellung eines Dekorators führte die falsche Übergabe von Parametern (Reihenfolge und Struktur nicht eingehalten) dazu, dass die Originalfunktion nicht die richtige Anzahl von Argumenten erhielt, deren Vereinbarung sich änderten, was in der Produktion zu TypeError führte.