Introduzione
Le tuple sono una delle strutture dati più utili in Python quando hai bisogno di raggruppare valori in modo semplice, ordinato e immutabile. Molti programmatori le conoscono per l’immutabilità o per l’unpacking, ma c’è un aspetto molto pratico che spesso viene sottovalutato: usare le tuple come valore di ritorno delle funzioni.
Questo approccio è estremamente comune nel codice reale. Una funzione può dover restituire più informazioni contemporaneamente: un risultato, uno stato, un messaggio di errore, coordinate, statistiche, configurazioni elaborate. In questi casi, la tuple è spesso la soluzione più pulita rispetto a soluzioni più complesse o meno leggibili.
In questo tutorial vedremo come usare le tuple per restituire più valori da una funzione, come leggerle correttamente, quando sono preferibili ad altri approcci e quali errori evitare. L’obiettivo è imparare un pattern molto usato nello sviluppo Python professionale.
Codice completo
from typing import Tuple
def calcola_sconto(prezzo: float, percentuale: float) -> Tuple[float, str]:
"""
Calcola il prezzo scontato e restituisce:
- il nuovo prezzo
- un messaggio descrittivo
"""
if prezzo < 0:
return 0.0, "Prezzo non valido"
if percentuale < 0 or percentuale > 100:
return prezzo, "Percentuale di sconto non valida"
sconto = prezzo * percentuale / 100
prezzo_finale = prezzo - sconto
return prezzo_finale, "Sconto applicato correttamente"
def analizza_vendite(vendite: list[float]) -> Tuple[float, float, float]:
"""
Restituisce:
- vendita minima
- vendita massima
- media delle vendite
"""
if not vendite:
return 0.0, 0.0, 0.0
minimo = min(vendite)
massimo = max(vendite)
media = sum(vendite) / len(vendite)
return minimo, massimo, media
def valida_utente(nome: str, eta: int) -> Tuple[bool, str]:
"""
Restituisce:
- True/False per indicare se i dati sono validi
- un messaggio esplicativo
"""
if not nome.strip():
return False, "Il nome non può essere vuoto"
if eta < 0:
return False, "L´età non può essere negativa"
if eta < 18:
return False, "Utente minorenne"
return True, "Utente valido"
# --- Esempi di utilizzo ---
prezzo_finale, messaggio = calcola_sconto(120.0, 15)
print(prezzo_finale)
print(messaggio)
min_vendita, max_vendita, media_vendite = analizza_vendite([120.0, 99.5, 140.0, 88.0])
print(min_vendita, max_vendita, media_vendite)
esito, descrizione = valida_utente("Luca", 21)
print(esito, descrizione)
# Le tuple possono essere restituite anche senza parentesi esplicite
risultato = calcola_sconto(200.0, 10)
print(risultato)
# Accesso per indice, se necessario
print(risultato[0])
print(risultato[1]) Spiegazione
La caratteristica più interessante del codice è che ogni funzione restituisce più valori in un’unica istruzione return. In Python, quando scrivi:
return prezzo_finale, "Sconto applicato correttamente" stai in realtà restituendo una tuple composta da due elementi. Le parentesi non sono obbligatorie: Python costruisce la tupla automaticamente.
1. Restituire più valori in modo naturale
In molti linguaggi, per restituire più informazioni devi creare una struttura più complessa. In Python, invece, puoi semplicemente usare una tupla. Questo rende il codice più leggibile e riduce la necessità di creare classi o dizionari quando non servono davvero.
Per esempio, la funzione calcola_sconto restituisce:
- il prezzo finale
- un messaggio descrittivo
Questo è utile perché chi chiama la funzione può decidere subito come usare i risultati.
2. Unpacking del valore restituito
Quando una funzione restituisce una tupla, puoi assegnare i valori direttamente a più variabili:
prezzo_finale, messaggio = calcola_sconto(120.0, 15) Questa tecnica si chiama unpacking e rende il codice molto più chiaro rispetto all’accesso tramite indici, ad esempio risultato[0] e risultato[1].
Usare le variabili separate comunica immediatamente il significato dei dati.
3. Tupla di dimensione variabile ma struttura stabile
Nel nostro esempio, analizza_vendite restituisce sempre tre valori:
- minimo
- massimo
- media
Questo è molto utile quando vuoi mantenere una firma di ritorno stabile. Chi usa la funzione sa sempre cosa aspettarsi, e il codice diventa più prevedibile.
4. Quando una tupla è meglio di un dizionario
Se i dati sono pochi, ben definiti e con ordine preciso, la tupla è spesso una scelta migliore del dizionario. Ad esempio, per restituire coordinate, statistiche o un risultato con stato e messaggio, la tupla è più leggera e immediata.
Un dizionario diventa più adatto quando i campi sono molti, opzionali o semanticamente complessi. Ma per ritorni semplici, la tupla resta una soluzione elegante.
5. Tipizzazione con typing.Tuple
Nel codice abbiamo usato annotazioni di tipo come:
def calcola_sconto(prezzo: float, percentuale: float) -> Tuple[float, str]: Questo aiuta editor, IDE e strumenti di analisi statica a capire cosa restituisce la funzione. È una buona pratica soprattutto nei progetti medio-grandi, dove la chiarezza dei contratti tra funzioni è fondamentale.
Se usi Python 3.10 o superiore, puoi anche scrivere:
def calcola_sconto(prezzo: float, percentuale: float) -> tuple[float, str]: Questa sintassi è più moderna e leggibile.
Best practice
- Usa tuple per ritorni piccoli e ben definiti: due o tre valori sono un caso perfetto.
- Dai nomi chiari alle variabili in unpacking: evita nomi generici come
a,b,c. - Evita tuple troppo lunghe: se devi restituire molti valori, valuta una classe, un dataclass o un dizionario.
- Documenta sempre l’ordine dei valori: una tupla è ordinata, quindi l’ordine è parte del contratto della funzione.
- Usa le annotazioni di tipo per rendere il codice più leggibile e mantenibile.
- Non accedere agli elementi con indici se puoi evitarlo: l’unpacking è quasi sempre più chiaro.
Un errore comune è restituire tuple senza spiegare bene cosa contengono. Per esempio, una funzione che ritorna (True, 18, "ok") può diventare difficile da mantenere se non è chiaro il significato di ogni posizione. In questi casi, meglio usare nomi più espliciti o una struttura dedicata.
Quando evitare le tuple come return
Le tuple non sono sempre la scelta ideale. Evitale quando:
- i dati sono numerosi e difficili da ricordare
- i campi sono opzionali o variabili
- serve maggiore semantica nei nomi dei valori
- devi evolvere spesso la struttura del dato
In questi scenari, una dataclass può essere più adatta perché rende i campi espliciti e auto-documentati.
Riepilogo
Le tuple sono uno strumento molto utile in Python non solo come contenitori immutabili, ma anche come modo semplice e professionale per restituire più valori da una funzione. Questo pattern è comune, leggibile e perfettamente in linea con lo stile idiomatico di Python.
Abbiamo visto che:
- una funzione può restituire automaticamente una tuple con più valori
- l’unpacking rende il codice chiaro e facile da leggere
- le tuple sono ideali per risultati piccoli e ben strutturati
- le annotazioni di tipo migliorano manutenzione e comprensione
- per strutture più complesse è meglio valutare alternative come dataclass o dizionari
Se vuoi scrivere codice Python pulito e professionale, imparare a usare bene le tuple come valori di ritorno è una competenza fondamentale.
Approfondisci con risorse ufficiali
- Documentazione ufficiale Python sulle tuple: https://docs.python.org/3/library/stdtypes.html#tuple
- Documentazione ufficiale su return statement: https://docs.python.org/3/reference/simple_stmts.html#the-return-statement
- Documentazione su typing: https://docs.python.org/3/library/typing.html
- PEP 484 - Type Hints: https://peps.python.org/pep-0484/
Se vuoi, nel prossimo tutorial posso mostrarti un confronto pratico tra tuple, dataclass e dizionari per restituire dati da una funzione.
