Corso Python / Argomenti posizionali, keyword e valori predefiniti
Gli argomenti di una funzione possono essere passati per posizione o per nome, e i valori predefiniti rendono alcuni parametri facoltativi. Se ogni chiamata deve partire da uno stato nuovo, evita un oggetto modificabile condiviso come valore predefinito.
Rendere chiaro il significato degli argomenti
Gli argomenti posizionali vengono associati ai parametri nell’ordine; quelli keyword usano il nome del parametro. Puoi quindi rendere esplicito il significato delle opzioni senza dipendere solo dalla loro posizione. Non puoi fornire due valori allo stesso parametro: uno per posizione e un altro per nome genera TypeError.
Un normale argomento posizionale scritto dopo un argomento keyword è un errore di sintassi. Nel codice della definizione, i parametri dopo un asterisco isolato * sono invece keyword-only: devono essere indicati per nome nella chiamata. Nell’esempio currency è un’opzione di questo tipo, così l’unità risulta leggibile.
La guida alle funzioni e ai parametri chiarisce i termini; la documentazione ufficiale di valori predefiniti e argomenti keyword descrive queste regole di chiamata.
Eseguire argomenti keyword-only e liste nuove
Salva il programma completo come arguments.py in UTF-8, dentro una cartella di esercitazione. Esegui python arguments.py con l’interprete del progetto selezionato. Su macOS o Ubuntu fuori dall’ambiente virtuale usa python3 se è il comando dell’interprete scelto. Non servono pacchetti esterni.
def format_expense(name, amount, *, currency="KRW"):
return f"{name}: {amount:,} {currency}"
def append_name(name, names=None):
if names is None:
names = []
names.append(name)
return names
print(format_expense("lunch", 8000))
print(format_expense(amount=9000, name="dinner", currency="KRW"))
print(append_name("A"))
print(append_name("B"))
Il risultato atteso è:
lunch: 8,000 KRW
dinner: 9,000 KRW
['A']
['B']
La prima chiamata usa il valore predefinito KRW. La seconda passa gli argomenti per nome: il loro ordine nella chiamata non deve corrispondere a quello della definizione. Currency è un’etichetta usata nell’output, non esegue una conversione valutaria.
Le due chiamate ad append_name senza lista esplicita ricevono None e creano ciascuna una lista nuova. Per questo la seconda stampa contiene soltanto B, senza A. L’uso di is None distingue l’assenza di una lista da una lista vuota passata intenzionalmente.
Capire quando viene creato il valore predefinito
Le espressioni dei valori predefiniti vengono valutate quando viene eseguita la definizione della funzione, non ogni volta che viene chiamata. Con names=[] quella stessa lista è riutilizzata dalle chiamate che omettono l’argomento. Con None, invece, la creazione dentro il corpo viene eseguita per ogni chiamata che richiede una nuova lista.
Salva questo secondo programma completo come defaults.py nella stessa cartella ed esegui python defaults.py. Le chiamate successive nello stesso processo rendono osservabile la condivisione:
def shared(name, names=[]):
names.append(name)
return names
def fresh(name, names=None):
if names is None:
names = []
names.append(name)
return names
print(shared("A"))
print(shared("B"))
print(fresh("A"))
print(fresh("B"))
Il risultato atteso è:
['A']
['A', 'B']
['A']
['B']
Shared conserva A e aggiunge B alla stessa lista. Fresh produce una lista per ogni chiamata senza argomento names. Una nuova esecuzione del file esegue di nuovo le definizioni, quindi non è equivalente a due chiamate consecutive alla stessa funzione già definita.
Non sostituire if names is None con if not names se devi conservare una lista vuota fornita dal chiamante. Una lista vuota è falsa in un controllo logico: il secondo controllo la rimpiazzerebbe, interrompendo la condivisione intenzionale con chi l’ha passata.
Verificare interfaccia e modifiche degli oggetti
- Nel primo esempio prova
format_expense("lunch", 8000, "KRW"): il terzo argomento posizionale viene rifiutato con TypeError. Passalo invece comecurrency="KRW"per rispettare la firma. - Crea fuori dalla funzione
names = []e chiamaappend_name("A", names). La lista del chiamante diventa["A"]: è una modifica intenzionale dell’oggetto fornito, distinta dal problema del valore predefinito condiviso. - Confronta questa chiamata con due chiamate prive dell’argomento names e verifica quali risultati condividono la stessa lista.
- Ripristina i due file originali e confronta entrambi gli output.
Una funzione che riceve una lista non la copia automaticamente. Dichiarare un parametro con None evita il riuso involontario del valore predefinito, ma non rende indipendenti gli oggetti esplicitamente passati. Il contratto della funzione deve dire se modifica la lista del chiamante.
Lo stesso momento di valutazione riguarda un’espressione che calcola data o ora corrente: se la usi come valore predefinito, conserva il risultato della definizione. Per ottenere un valore nuovo a ogni chiamata, ricevi None e calcolalo nel corpo. Se None stesso è un argomento valido con un significato distinto, usa un marcatore dedicato per rappresentare l’argomento omesso.




