Python jest fajny, bo jest dynamiczny. Napiszesz sobie funkcję, a potem ni z tego ni z owego można ją wywoływać na wiele sposobów. Popatrz na ten przykład:
def show_args(arg_1, arg_2): print(arg_1) print(arg_2) show_args('one','two')
Proste? No pewnie, że proste! Funkcja ma dwa argumenty i wywołujemy ją z dwoma argumentami i już!
Ale może by tak, mając listę dwóch elementów przekazać ją do tej funkcji? Może funkcja będzie na tyle sprytna, żeby zrozumieć o co chodzi? Niestety będzie błąd:
show_args(['one','two']) TypeError: show_args() missing 1 required positional argument: 'arg_2'
… ale gdyby tak, przed listą dodać gwiazdkę, to Python „wyłuska z listy jej elementy i przekaże je do funkcji:
show_args(*['one','two']) one two
Wow! Dobre!
No a jeśli nie mamy listy argumentów, tylko słownik? I jeśli jeszcze w tym słowniku elementy są „przypadkowo” nazwane tak, jak argumenty testowanej funkcji? Przy pierwszym podejściu – niestety klapa:
show_args({'arg_2':'two', 'arg_1':'one'}) TypeError: show_args() missing 1 required positional argument: 'arg_2'
Ale my już wiemy, jak sobie z tym poradzić:
show_args(*{'arg_2':'two', 'arg_1':'one'}) arg_2 arg_1
Jedna gwiazdka jakoś już pomogła, niestety, pewnie wolelibyśmy nie zobaczyć w wyniku funkcji nazw kluczy, tylko ich wartości! Z pomocą przyjdą dwie gwiazdki, które konwertują słownik na nazwane wartości przekazywane do funkcji:
show_args(**{'arg_2':'two', 'arg_1':'one'}) one two
I to już działa idealnie. Funkcja domyśliła się, co to jest arg_1 mimo tego, że ta wartość w słowniku była dopiero na drugim miejscu.
Fajnie, ale te „chwyty” można też wykorzystać definiując funkcję:
def clever_function(*args): for a in args: print(a) clever_function(1,2,3)
Kiedy chcesz, aby funkcja mogła przyjąć dowolną liczbę parametrów przekazywanych po prostu przez pozycję, to wystarczy zadeklarować argumenty jako *args. W ciele funkcji można wtedy skorzystać ze zmiennej args, która jest listą. Bardzo to elastyczne!
Jeśli z kolei chcesz, aby funkcja miała przyjmować dowolną liczbę argumentów ze słownika, to argument poprzedź dwoma gwiazdkami. Zazwyczaj ten parametr nazywamy kwargs (key-word argument):
def clever_function(**kwargs): for k, v in kwargs.items(): print(k,v) clever_function(a=1,b=2,c=3)
Teraz do funkcji można przekazywać dowolną liczbę nazwanych parametrów, a funkcja w sprytny sposób zobaczy je jako słownik. To użytkownik wywołując funkcję sam decyduje o tym, jak mają się nazywać argumenty widoczne w funkcji.
Obie te metody można zresztą połączyć i zbudować funkcję tak:
def clever_function(*args, **kwargs): for a in args: print(a) for k, v in kwargs.items(): print(k,v) clever_function('one','two',a=1,b=2,c=3) print('---') clever_function(a=1,b=2,c=3) print('---') clever_function('one','two')
Jak widać funkcję można teraz wywoływać z argumentami określanymi przez pozycję i nazwę, albo tylko przez nazwę albo tylko przez pozycję.
Oj przyda się na pewno!