*args verzamelt een willekeurig aantal positionele argumenten in een tuple.
**kwargs verzamelt een willekeurig aantal benoembare argumenten (sleutel=waarde) in een woordenboek.
Dit stelt je in staat om functies met een flexibele interface te schrijven:
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}
Fijnere details:
Kan de volgorde van *args en benoembare argumenten met een standaardwaarde bijvoorbeeld worden omgewisseld:
def foo(a, *args, x=10, **kwargs): pass
of moeten standaardwaarden altijd na *args komen?
Antwoord:
In Python 3 kan dit! Zo (werkte niet in Python 2):
def foo(a, *args, x=10): pass
Parameters na *args ("sleutel-alleen argumenten") kunnen standaardwaarden hebben of verplicht zijn — ze kunnen alleen bij naam worden opgegeven.
Verhaal
Verkeerde argumenten doorgeven via *args/**kwargs
In REST API-services was de automatisering van de gegevensverwerking gebaseerd op **kwargs. Een extra parameter werd niet opgemerkt — de functie ontving een onverwachte waarde in kwargs, wat leidde tot verlies van controlelogica en moeilijke, te debuggen bugs.
Verhaal
Duplicatie van benoembare argumenten
Bij het aanroepen van de functie gaf de ontwikkelaar per ongeluk een parameter zowel expliciet als via **kwargs op, bijvoorbeeld: my_func(a=1, **{"a": 2}). Het gevolg was een TypeError en een crash van de service.
Verhaal
Vergeet positionele of alleen benoembare argumenten
Bij het schrijven van een decorator leidde een verkeerde doorgegeven parameters (de volgorde en structuur werden niet nageleefd) ertoe dat de oorspronkelijke functie niet het juiste aantal argumenten ontving, waardoor er TypeError-aanroepfouten ontstonden in productie.