2.15. Argumente

O funcție poate fi apelată în mai multe moduri, iar parametrii ei pot fi declarați în mai multe forme. La început, combinațiile par intimidante; în practică, trei sau patru tipare acoperă aproape totul.

2.15.1. Argumente poziționale și de tip cuvânt-cheie

Cel mai simplu apel transmite argumentele prin poziție – prima valoare merge la primul parametru, a doua la al doilea și așa mai departe:

def rect(x, y, w, h):
    return (x, y, w, h)

rect(10, 20, 100, 50)

Același apel poate transmite argumentele prin cuvânt-cheie, numind explicit fiecare parametru:

rect(x=10, y=20, w=100, h=50)

Argumentele de tip cuvânt-cheie sunt independente de ordine și fac apelurile autoexplicative, cu prețul unei scrieri mai lungi. Argumentele poziționale și cele de tip cuvânt-cheie se pot combina într-un singur apel, dar fiecare argument pozițional trebuie să apară înaintea oricărui argument de tip cuvânt-cheie:

rect(10, 20, w=100, h=50)         # OK
rect(x=10, 20, 100, 50)           # SyntaxError

2.15.2. Valori implicite

Un parametru poate declara o valoare implicită care se folosește atunci când apelantul nu furnizează una:

def greet(name, greeting="hello"):
    print(greeting, name)

greet("Alice")                    # hello Alice
greet("Alice", "hi")              # hi Alice
greet("Alice", greeting="hey")    # hey Alice

Parametrii cu valori implicite trebuie să apară după parametrii fără valori implicite în linia def.

Atenționare

Valorile implicite sunt evaluate o singură dată, atunci când se execută def – nu la fiecare apel. Folosirea unei valori implicite mutabile ([], {}) face ca același obiect să fie partajat de toate apelurile care preiau valoarea implicită. Folosește None ca valoare santinelă în schimb:

def append_to(item, target=None):
    if target is None:
        target = []
    target.append(item)
    return target

2.15.3. Lungime variabilă: *args și **kwargs

Un parametru prefixat cu * colectează orice argumente poziționale rămase într-un tuple. Un parametru prefixat cu ** colectează orice argumente de tip cuvânt-cheie rămase într-un dict. Numele convenționale sunt args și kwargs, dar orice identificator funcționează:

def report(label, *values, **options):
    print(label, values, options)

report("temps", 21, 22, 23, unit="C", precision=1)

Ieșire:

temps (21, 22, 23) {'unit': 'C', 'precision': 1}

Rareori o funcție are nevoie de ambele. Cea mai frecventă utilizare este redirecționarea argumentelor de la un înveliș (wrapper) către un apel interior:

def log_and_call(func, *args, **kwargs):
    print("calling", func.__name__)
    return func(*args, **kwargs)

Sintaxa în oglindă de la locul apelului despachetează un iterabil în argumente poziționale (*) sau un dict în argumente de tip cuvânt-cheie (**):

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. Parametri exclusiv de tip cuvânt-cheie

Un * de sine stătător în lista de parametri (neatașat unui nume) marchează fiecare parametru care urmează ca fiind exclusiv de tip cuvânt-cheie – apelantul trebuie să folosească numele:

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

Folosește acest lucru pentru indicatorii booleeni și alte argumente unde o valoare simplă la locul apelului nu ar fi autoexplicativă.