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.