2.15. Argumenty¶
Funkcję można wywołać na kilka sposobów, a jej parametry można zadeklarować w kilku postaciach. Kombinacje wyglądają na początku onieśmielająco; w praktyce trzy lub cztery wzorce pokrywają niemal wszystko.
2.15.1. Argumenty pozycyjne i nazwane¶
Najprostsze wywołanie przekazuje argumenty według pozycji – pierwsza wartość trafia do pierwszego parametru, druga do drugiego i tak dalej:
def rect(x, y, w, h):
return (x, y, w, h)
rect(10, 20, 100, 50)
To samo wywołanie może przekazać argumenty według nazwy, jawnie nazywając każdy parametr:
rect(x=10, y=20, w=100, h=50)
Argumenty nazwane są niezależne od kolejności i czynią wywołania samodokumentującymi kosztem większej ilości pisania. Argumenty pozycyjne i nazwane można mieszać w jednym wywołaniu, ale każdy pozycyjny musi pojawić się przed jakimkolwiek nazwanym:
rect(10, 20, w=100, h=50) # OK
rect(x=10, 20, 100, 50) # SyntaxError
2.15.2. Wartości domyślne¶
Parametr może zadeklarować wartość domyślną używaną wtedy, gdy wywołujący jej nie poda:
def greet(name, greeting="hello"):
print(greeting, name)
greet("Alice") # hello Alice
greet("Alice", "hi") # hi Alice
greet("Alice", greeting="hey") # hey Alice
Parametry z wartościami domyślnymi muszą wystąpić po parametrach bez wartości domyślnych w wierszu def.
Ostrzeżenie
Wartości domyślne są obliczane raz, gdy wykonywany jest def – a nie przy każdym wywołaniu. Użycie zmiennej wartości domyślnej ([], {}) powoduje, że ten sam obiekt jest współdzielony przez każde wywołanie korzystające z wartości domyślnej. Zamiast tego użyj None jako wartości strażniczej:
def append_to(item, target=None):
if target is None:
target = []
target.append(item)
return target
2.15.3. Zmienna liczba argumentów: *args i **kwargs¶
Parametr poprzedzony * zbiera wszystkie pozostałe argumenty pozycyjne do tuple. Parametr poprzedzony ** zbiera wszystkie pozostałe argumenty nazwane do dict. Konwencjonalne nazwy to args i kwargs, ale działa dowolny identyfikator:
def report(label, *values, **options):
print(label, values, options)
report("temps", 21, 22, 23, unit="C", precision=1)
Wyjście:
temps (21, 22, 23) {'unit': 'C', 'precision': 1}
Funkcja rzadko potrzebuje obu. Najczęstszym zastosowaniem jest przekazywanie argumentów z opakowania do wewnętrznego wywołania:
def log_and_call(func, *args, **kwargs):
print("calling", func.__name__)
return func(*args, **kwargs)
Lustrzana składnia w miejscu wywołania rozpakowuje obiekt iterowalny do argumentów pozycyjnych (*) lub dict do argumentów nazwanych (**):
point = (10, 20, 100, 50)
rect(*point) # same as rect(10, 20, 100, 50)
kwargs = {"x": 10, "y": 20, "w": 100, "h": 50}
rect(**kwargs) # same as rect(x=10, y=20, ...)
2.15.4. Parametry wyłącznie nazwane¶
Samo * na liście parametrów (niedołączone do nazwy) oznacza każdy następujący po nim parametr jako wyłącznie nazwany – wywołujący musi użyć nazwy:
def crop(buffer, *, x, y, w, h):
...
crop(buffer, x=0, y=0, w=100, h=100) # OK
crop(buffer, 0, 0, 100, 100) # TypeError
Użyj tego dla flag logicznych i innych argumentów, gdzie sama wartość w miejscu wywołania nie byłaby samoobjaśniająca.