2.15. Argomenti¶
Una funzione può essere chiamata in diversi modi e i suoi parametri possono essere dichiarati in diverse forme. All’inizio le combinazioni sembrano intimidatorie; in pratica tre o quattro schemi coprono quasi tutto.
2.15.1. Argomenti posizionali e per parola chiave¶
La chiamata più semplice passa gli argomenti per posizione: il primo valore va al primo parametro, il secondo al secondo, e così via:
def rect(x, y, w, h):
return (x, y, w, h)
rect(10, 20, 100, 50)
La stessa chiamata può passare gli argomenti per parola chiave, nominando esplicitamente ciascun parametro:
rect(x=10, y=20, w=100, h=50)
Gli argomenti per parola chiave sono indipendenti dall’ordine e rendono le chiamate auto-documentate, al costo di scrivere di più. Argomenti posizionali e per parola chiave possono coesistere in un’unica chiamata, ma ogni argomento posizionale deve precedere qualsiasi argomento per parola chiave:
rect(10, 20, w=100, h=50) # OK
rect(x=10, 20, 100, 50) # SyntaxError
2.15.2. Valori predefiniti¶
Un parametro può dichiarare un valore predefinito da usare quando il chiamante non ne fornisce uno:
def greet(name, greeting="hello"):
print(greeting, name)
greet("Alice") # hello Alice
greet("Alice", "hi") # hi Alice
greet("Alice", greeting="hey") # hey Alice
Nella riga def, i parametri con valori predefiniti devono venire dopo quelli senza valori predefiniti.
Avvertimento
I valori predefiniti vengono valutati una sola volta, quando viene eseguito il def, non a ogni chiamata. Usare un valore predefinito mutabile ([], {}) fa sì che lo stesso oggetto venga condiviso tra tutte le chiamate che usano il valore predefinito. Usa invece None come sentinella:
def append_to(item, target=None):
if target is None:
target = []
target.append(item)
return target
2.15.3. Lunghezza variabile: *args e **kwargs¶
Un parametro preceduto da * raccoglie tutti gli argomenti posizionali rimanenti in una tuple. Un parametro preceduto da ** raccoglie tutti gli argomenti per parola chiave rimanenti in un dict. I nomi convenzionali sono args e kwargs, ma funziona qualsiasi identificatore:
def report(label, *values, **options):
print(label, values, options)
report("temps", 21, 22, 23, unit="C", precision=1)
Output:
temps (21, 22, 23) {'unit': 'C', 'precision': 1}
Raramente una funzione ha bisogno di entrambi. L’uso più comune è inoltrare gli argomenti da un wrapper a una chiamata interna:
def log_and_call(func, *args, **kwargs):
print("calling", func.__name__)
return func(*args, **kwargs)
La sintassi speculare nel sito di chiamata spacchetta un iterabile in argomenti posizionali (*) oppure un dict in argomenti per parola chiave (**):
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 solo per parola chiave¶
Un * da solo nell’elenco dei parametri (non collegato a un nome) contrassegna ogni parametro successivo come solo per parola chiave: il chiamante deve usare il nome:
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
Usalo per i flag booleani e per altri argomenti in cui un valore nudo nel sito di chiamata non sarebbe auto-esplicativo.