Zadanie
Dana jest funkcja:
def nic_nie_robie(param_1, param_2, param_3=None): print(param_1) print(param_2) print(param_3)
Które z poniższych wywołań naszej funkcji są poprawne ?
nic_nie_robie(1,2)
nic_nie_robie(*[1, 2])
nic_nie_robie(**{'param_1' : 1, 'param_2' : 2, 'param_3' : 3})
nic_nie_robie(*{'param_1' : 1, 'param_2' : 2, 'param_3' : 3})
nic_nie_robie(param_1=1,2,3)
Odpowiedź
Standardowe pytanie a,b,c,d wielokrotnego wyboru i żadna odpowiedz nie jest poprawna. Nie no żartowałem nie zadziała jedynie wywołanie funkcji nr 5. Oznacza to, że cała reszta wywołań jest poprawna. Odpowiedzmy sobie teraz dlaczego.
Funkcja 1 nic_nie_robie(1,2)
Jak pewnie zauważyłeś nasza funkcja przyjmuje trzy argumenty. W tym wywołaniu przesyłamy tylko dwa. Możemy tak zrobić ponieważ trzeci parametr param_3 ma zdefiniowaną wartość domyślną.
Funkcja 2 nic_nie_robie(*[1, 2])
Jakby się zastanowić to takie wywołania naszej funkcji jest ekwiwalentem poprzedniego. Do funkcji prześlemy jedynie wartość 1 jako param_1 oraz wartość 2 jako param_2. Trzeci parametr param_3 dostanie wartość domyślną None, jednak jest pewna różnica. Do funkcji przekazujemy listę z tym, że zanim to zrobimy rozpakowujemy ją za pomocą operatora ”*”. Właśnie dzięki temu do funkcji nie trafia cała lista tylko po kolei jej elementy.
Funkcja 3 nic_nie_robie(**{'param_1' : 1, 'param_2' : 2, 'param_3' : 3})
Tu znowu mamy zabawę z rozpakowywaniem. Tym razem operacji rozpakowania podlega słownik. By rozpakować słownik należy posłużyć się operatorem podwójnej gwiazdki ”**”. Takie wywołanie naszej funkcji będzie jednoznaczne takiemu:
nic_nie_robie(param_1=1, param_2=2, param_3=3)
Zatem klucze naszej mapy stają się nazwami parametrów, natomiast korespondujące z nimi wartości ich wartościami. Ten trik jest bardzo często używany jako swego rodzaju adapter na istniejące już funkcje i metody.
Funkcja 4 nic_nie_robie(*{'param_1' : 1, 'param_2' : 2, 'param_3' : 3})
Przy tej odpowiedzi dużo ludzi popełnia błąd. Nic dziwnego bo nie jest ono jednoznaczne. Dlatego niezależnie od tego jaką odpowiedz udzieliłeś możesz mieć rację. Faktem jest, że taki kod jest poprawny i zadziała. Jednakże przecież przed chwilą mówiliśmy, że słowniki rozpakowuje się za pomocą dwóch gwiazdek ”**”, a tu mamy przecież tylko jedną, czyli ”*”. Jedna gwiazdka ”*” służyła do rozpakowywania list. Dlatego w tym przypadku do funkcji trafią same klucze z naszego słownika. Pytanie brzmi czy jest to pożądane zachowanie czy nie.
Funkcja 5 nic_nie_robie(param_1=1,2,3)
Tu mamy błąd. SyntaxError: positional argument follows keyword argument
.
Powód jest bardzo prosty. Argumenty pozycyjne muszą być zawsze po argumentach niepozycyjnych.