Funkcje napisane w języku Python mają możliwość akceptowania opcjonalnych parametrów. Przyjrzyjmy się poniższemu snippetowi.
1 2 3 4 5 6 7 |
def args_kwargs(*args, **kwargs): if args: print(args) if kwargs: print(kwargs) |
Jeżeli wywołamy tę funkcję w następujący sposób:
1 2 3 |
args_kwargs(1, 2, '3', first='first', second='second', third='third') |
Otrzymamy następujący wynik:
1 2 3 4 |
(1, 2, '3') {'first': 'first', 'second': 'second', 'third': 'third'} |
Argumenty pozycyjne zostały skumulowane w tuplu *args, a argumenty nazwane w słowniku **kwargs. Co się stanie gdy wywołamy tę funkcję bez argumentów:
1 2 3 |
args_kwargs() |
Nic się nie wydarzyło, błędu też nie ma. Więc argumenty *args i **kwargs nie są wymagane. Dodajmy dodatkowy argument arg_1 i wywołajmy tę funkcję z poprzednimi argumentami.
1 2 3 4 5 6 7 8 9 10 11 12 |
def args_kwargs(arg_1, *args, **kwargs): if args: print(args) if kwargs: print(kwargs) args_kwargs(1, 2, '3', first='first', second='second', third='third') # (2, '3') # {'first': 'first', 'second': 'second', 'third': 'third'} |
Z tupla *args znikneła nam 1. Wypiszmy brakujący arg_1 i wywołajmy funkcję jeszcze raz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
def args_kwargs(arg_1, *args, **kwargs): print(f"arg_1 = {arg_1}") if args: print(args) if kwargs: print(kwargs) args_kwargs(1, 2, '3', first='first', second='second', third='third') # arg_1 = 1 # (2, '3') # {'first': 'first', 'second': 'second', 'third': 'third'} |
Co się stanie jak wywołamy funkcję bez argumentów?
1 2 3 4 5 6 7 8 |
args_kwargs() Traceback (most recent call last): File "args_kwargs.py", line 2, in args_kwargs() TypeError: args_kwargs() missing 1 required positional argument: 'arg_1' |
No tak arg_1 jest wymagany. Potestujmy tę funkcję i zobaczmy do jakich dojdziemy wniosków.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
args_kwargs(1) # arg_1 = 1 args_kwargs(1, first='first') # arg_1 = 1 # {'first': 'first'} args_kwargs(1, 1, 1) # arg_1 = 1 # (1, 1) args_kwargs(1, 1, second='second') # arg_1 = 1 # (1,) # {'second': 'second'} args_kwargs(1, 1, second='second', 1) # args_kwargs(1, 1, second='second', 1) # ^ # SyntaxError: positional argument follows keyword argument args_kwargs(arg_1=1, 1, second='second') # args_kwargs(arg_1=1, 1, second='second') # ^ # SyntaxError: positional argument follows keyword argument |
A więc w Pythonie istotna jest kolejność argumentów pierwszy od lewej przypisany jest do arg_1 kolejne pozycyjne są umieszczane w tuplu *args a argumenty nazwane są kumulowane w słowniku **kwargs. Jeżeli odwrócimy w jakiś sposób kolejność argumentów zostanie zwrócony SyntaxError. Warto wspomnieć, że nazwy *args oraz **kwargs to tylko przyjęta konwencja równie dobrze możesz użyć *positional_arguments, **named_arguments. Ważne aby zapamiętać, że prefix * oznacza tuple a prefix ** słownik.