W3docs

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())                 # 0

Innerhalb 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 York

Innerhalb 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:

  1. Normale positionelle Parameter
  2. *args
  3. Nur-Schlüsselwort-Parameter (mit Standardwerten)
  4. **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: True

port 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: {}
# 6

Dieses 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:

PositionArtBeispiel
1Nur-positionell (Python 3.8+)a, b, /
2Normal positionell-oder-Schlüsselwortx, y
3Variable positionell*args
4Nur-Schlüsselwortflag=True
5Variable 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):
    pass

2. 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

FunktionSyntaxWas gesammelt wirdTyp innerhalb der Funktion
Variable positionelle Argumente*argsZusätzliche positionelle Argumentetuple
Variable Schlüsselwortargumente**kwargsZusätzliche Schlüsselwortargumentedict
Sequenz beim Aufruf entpackenfunc(*seq)Liste/Tuple → positionelle Argumente
Mapping beim Aufruf entpackenfunc(**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.

Übungen

Übung
In Python, what does *args do when used in a function definition?
In Python, what does *args do when used in a function definition?
Was this page helpful?