Introduzione

Python 3.8, rilasciato nell'ottobre 2019, aggiunge espressioni di assegnazione (assignment expressions) a Python tramite la sintassi :=. La sintassi dell'espressione di assegnazione è talvolta chiamata anche "l'operatore del tricheco" (the walrus operator) perché := assomiglia vagamente a un tricheco con le zanne.

Le espressioni di assegnazione consentono l'assegnazione di variabili all'interno di espressioni più grandi. Sebbene le espressioni di assegnazione non siano mai strettamente necessarie per scrivere codice Python corretto, possono aiutare a rendere il codice Python esistente più conciso. Ad esempio, le espressioni di assegnazione che utilizzano la sintassi := consentono di assegnare variabili all'interno di istruzioni if, che spesso possono produrre sezioni più brevi e compatte di codice Python eliminando assegnazioni di variabili nelle righe che precedono o seguono l'istruzione if.

In questo tutorial, utilizzerai espressioni di assegnazione in diversi esempi per produrre sezioni di codice concise.

Prerequisiti

Per ottenere il massimo da questo tutorial, avrai bisogno di:

  • Python 3.8 o successivo. Le espressioni di assegnazione sono una nuova funzionalità aggiunta a partire da Python 3.8. È possibile visualizzare i tutorial di Python a questo indirizzo.
  • Una certa familiarità con i cicli while, le istruzioni if, le comprensioni di elenchi e le funzioni in Python 3 sono utili, ma non necessaria.

Utilizzare le espressioni di assegnazione nelle dichiarazioni if

Cominciamo con un esempio di come puoi usare le espressioni di assegnazione in un'istruzione if.

Considera il codice seguente che controlla la lunghezza di un elenco e stampa un'istruzione:

some_list = [1, 2, 3]
if (list_length := len(some_list)) > 2:
    print("List length of", list_length, "is too long")

Se esegui il codice precedente, riceverai il seguente output:

List length of 3 is too long

Si inizializza un elenco denominato some_list che contiene tre elementi. Quindi, l'istruzione if utilizza l'espressione di assegnazione ((list_length := len(some_list)) per associare la variabile denominata list_length alla lunghezza di some_list. L'istruzione if restituisce True perché list_length è maggiore di 2. Si stampa una stringa utilizzando la variabile list_length, che inizialmente è stata associata all'espressione di assegnazione, indicando che l'elenco dei tre elementi è troppo lungo.

Nota: le espressioni di assegnazione sono una nuova funzionalità introdotta in Python 3.8. Per eseguire gli esempi in questo tutorial, dovrai utilizzare Python 3.8 o versioni successive.

Se non avessimo usato l'espressione di assegnazione, il nostro codice avrebbe potuto essere leggermente più lungo. Per esempio:

some_list = [1, 2, 3]
list_length = len(some_list)
if list_length > 2:
    print("List length of", list_length, "is too long")

Questo esempio di codice è equivalente al primo esempio, ma questo codice richiede una riga autonoma aggiuntiva per associare il valore di list_length a len(some_list).

Un altro esempio di codice equivalente potrebbe eseguire len(some_list)due volte: una volta nell'istruzione if e una volta nell'istruzione print. Ciò eviterebbe di incorrere nella riga aggiuntiva richiesta per associare una variabile al valore di len(some_list):

some_list = [1, 2, 3]
if len(some_list) > 2:
    print("List length of", len(some_list), "is too long")

Le espressioni di assegnazione aiutano a evitare la riga aggiuntiva o il doppio calcolo.

Nota: le espressioni di assegnazione sono uno strumento utile, ma non sono strettamente necessarie. Usa il tuo giudizio e aggiungi espressioni di assegnazione al tuo codice quando migliora significativamente la leggibilità di un passaggio.

Nella sezione successiva, esploreremo l'utilizzo delle espressioni di assegnazione all'interno dei cicli while.

Utilizzare le espressioni di assegnazione nei cicli while

Le espressioni di assegnazione spesso funzionano bene nei loop while perché ci consentono di inserire più contesto nella condizione loop.

Considera il seguente esempio che incorpora una funzione input utente all'interno della condizione del ciclo while:

while (directive := input("Enter text: ")) != "stop":
    print("Received directive", directive)

Se esegui questo codice, Python ti chiederà continuamente l'inserimento di testo dalla tastiera finché non digiti la parola stop. Una sessione di esempio potrebbe essere simile a:

>>> while (directive := input("Enter text: ")) != "stop":
...     print("Received directive", directive)
...
Enter text: hello
Received directive hello
Enter text: example
Received directive example
Enter text: stop
>>>

L'espressione di assegnazione (directive := input("Enter text: ")) lega il valore di directive al valore recuperato dall'utente tramite la funzione input. Associate il valore di ritorno alla variabile directive, che stampate nel corpo del ciclo while. Il ciclo  while termina ogni volta che digiti stop.

Se non avessi usato un'espressione di assegnazione, potresti aver scritto un ciclo input equivalente come:

directive = input("Enter text: ")
while directive != "stop":
    print("Received directive", directive)
    directive = input("Enter text: ")

Questo codice è funzionalmente identico a quello con le espressioni di assegnazione, ma richiede quattro righe totali (invece di due righe). Inoltre duplica la chiamata input("Enter text: ") in due punti. Certamente, ci sono molti modi per scrivere un ciclo while equivalente, ma la variante dell'espressione di assegnazione introdotta in precedenza è compatta e cattura bene l'intenzione del programma.

Finora, hai utilizzato espressioni di assegnazione in istruzioni if e cicli while. Nella sezione successiva, utilizzerai un'espressione di assegnazione all'interno di una lista di comprensione.

Utilizzare espressioni di assegnazione nelle comprensioni di elenchi

Possiamo anche usare espressioni di assegnazione nelle comprensioni di elenchi. Le liste di comprensione consentono di creare elenchi in modo succinto iterando su una sequenza e potenzialmente aggiungendo elementi all'elenco che soddisfano alcune condizioni. Come le comprensioni di elenchi, possiamo usare espressioni di assegnazione per migliorare la leggibilità e rendere il nostro codice più conciso.

Considera il seguente esempio che utilizza una comprensione dell'elenco e un'espressione di assegnazione per creare un elenco di numeri interi moltiplicati:

def slow_calculation(x):
    print("Multiplying", x, "*", x)
    return x * x

[result for i in range(3) if (result := slow_calculation(i)) > 0]

Se esegui il codice precedente, riceverai quanto segue:

Multiplying 0 * 0
Multiplying 1 * 1
Multiplying 2 * 2
[1, 4]

Si definisce una funzione denominata slow_calculation che moltiplica il numero dato x con se stessa. Un elenco di comprensione un'iterazione poi attraverso 0, 1 e 2restituito da range(3). Un'espressione di assegnazione lega il valore result alla restituzione di slow_calculation con i. Si aggiunge result all'elenco di recente costruzione, a patto che sia maggiore di 0. In questo esempio, 0, 1 e 2 sono tutti multipli di se stessi, ma solo i risultati 1(1 * 1) e 4(2 * 2) soddisfano la condizioni maggiore di 0 e diventano parte della lista finale [1, 4].

La funzione slow_calculation non è necessariamente lenta in termini assoluti, ma ha lo scopo di illustrare un punto importante sull'efficienza. Considera un'implementazione alternativa dell'esempio precedente senza espressioni di assegnazione:

def slow_calculation(x):
    print("Multiplying", x, "*", x)
    return x * x

[slow_calculation(i) for i in range(3) if slow_calculation(i) > 0]

Eseguendolo, riceverai il seguente output:

Multiplying 0 * 0
Multiplying 1 * 1
Multiplying 1 * 1
Multiplying 2 * 2
Multiplying 2 * 2
[1, 4]

In questa variante del codice precedente, non usi espressioni di assegnazione. Invece, si richiama slow_calculation fino a due volte: una volta per assicurarsi che slow_calculation(i) sia maggiore di 0 e potenzialmente una seconda volta per aggiungere il risultato del calcolo all'elenco finale. 0 viene moltiplicato con se stesso una sola volta perché 0 * 0 non è maggiore di 0. Gli altri risultati, invece, vengono calcolati doppiamente perché soddisfano la condizione maggiore di 0, quindi i risultati vengono ricalcolati per entrare a far parte dell'elenco finale [1, 4].

Hai combinato espressioni di assegnazione con comprensioni di elenchi per creare blocchi di codice efficienti e concisi.

Conclusione

In questo tutorial, hai utilizzato espressioni di assegnazione per creare sezioni compatte di codice Python che assegnano valori a variabili all'interno di istruzioni if, cicli while e comprensioni di elenchi.

Per ulteriori informazioni su altre espressioni di assegnazione, puoi visualizzare PEP 572, il documento che inizialmente proponeva di aggiungere espressioni di assegnazione a Python.