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ă.