*args — zbiera dowolną liczbę pozycyjnych argumentów w krotce.
**kwargs — zbiera dowolną liczbę argumentów nazwanych (klucz=wartość) w słowniku.
Umożliwia to pisanie funkcji z elastycznym interfejsem:
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}
Zasady:
Czy można zamienić miejscami *args i argumenty nazwane z wartością domyślną, na przykład:
def foo(a, *args, x=10, **kwargs): pass
*czy wartości domyślne muszą zawsze być po args?
Odpowiedź:
W Pythonie 3 można! Oto jak (nie działało w Pythonie 2):
def foo(a, *args, x=10): pass
Parametry po *args ("argumenty tylko nazwane") mogą mieć wartości domyślne lub być obowiązkowe — można je podawać tylko według nazwy.
Historia
Przekazywanie niewłaściwych argumentów przez *args/**kwargs
W usługach REST API automatyzacja marszalu danych opierała się na **kwargs. Dodatni parametr nie został zauważony — funkcja przyjęła nieoczekiwaną wartość w kwargs, co prowadziło do utraty logiki kontrolnej i trudnych do debugowania błędów.
Historia
Duplikowanie argumentów nazwanych
Podczas wywołania funkcji programista przypadkowo wskazał parametr i jawnie, i przez **kwargs, na przykład: my_func(a=1, **{"a": 2}). W efekcie — TypeError i awaria usługi.
Historia
Zapomniano o pozycyjnych lub tylko nazwanych argumentach
Podczas pisania dekoratora niewłaściwe przekazanie parametrów (niedostosowanie kolejności i struktury) prowadziło do tego, że oryginalna funkcja otrzymywała niewłaściwą liczbę argumentów, co skutkowało na produkcji błędami wywołania TypeError.