Ultime funzionalità di Python
Questo articolo spiega le ultime funzionalità di Python.
Spiegheremo passo dopo passo le funzionalità più notevoli delle versioni Python 3.12 e 3.13 da un punto di vista pratico di applicazioni 'immediatamente utilizzabili'.
YouTube Video
Ultime funzionalità di Python
Negli ultimi anni, Python si è evoluto con un'enfasi non solo su 'facilità di scrittura' ma anche su 'robustezza, velocità e leggibilità'. Di seguito presentiamo le funzionalità più rilevanti introdotte nelle versioni Python dalla 3.12 alla 3.13.
Miglioramenti significativi nei messaggi di errore (Python 3.12)
In Python 3.12, gli errori vengono ora mostrati in modo più concreto e visivo. È possibile individuare immediatamente dove sono stati commessi errori e ridurre notevolmente il tempo di debugging.
1def calc_total(price, tax):
2 return price + price * tax
3
4result = calc_total(100, )- Gli argomenti mancanti vengono mostrati con la linea e la posizione corrispondente, così non ci si confonde nell'identificare la causa.
Uso pratico dell'istruzione 'match' (Pattern Matching Strutturale)
L'istruzione 'match' permette di descrivere in modo dichiarativo rami condizionali complessi e discriminazione delle strutture dati. La gestione di dizionari e strutture nidificate diventa particolarmente più leggibile.
1user = {"status": "active", "name": "Alice"}
2
3match user:
4 case {"status": "active", "name": name}:
5 print(f"Welcome back, {name}!")
6 case {"status": "inactive"}:
7 print("Please activate your account.")
8 case _:
9 print("Unknown user status.")- Poiché è possibile eseguire contemporaneamente ramificazioni condizionali ed estrazione dei dati, l'annidamento di istruzioni if diventa superfluo.
Pattern matching intuitivo per gestire dati nidificati
L'istruzione 'match' è efficace anche per dati strutturati come risposte JSON o di API.
1data = {"user": {"name": "Bob", "age": 25}}
2
3match data:
4 case {"user": {"name": name, "age": age}}:
5 print(f"{name} is {age} years old.")- Si possono estrarre solo gli elementi necessari in modo sicuro, riducendo la necessità di codice difensivo.
Output di debug f-string migliorato (notazione =` / Python 3.8 e successivi, usabilità migliorata)
Con le f-string è ora possibile aggiungere = per visualizzare sia l'espressione sia il suo risultato di valutazione allo stesso tempo. Questa funzione è specializzata per il debugging ed è estremamente utile quando si desidera controllare rapidamente il contenuto di una variabile.
1x = 10
2y = 20
3print(f"{x=}, {y=}, {x+y=}")- Poiché i nomi e i valori delle variabili vengono mostrati insieme, il debugging temporaneo con istruzioni
print()diventa più leggibile. - È possibile scrivere output di log e codice di verifica in modo più conciso ed espressivo.
Suggerimenti di tipo e alias 'type' semplificati (Python 3.12: nuova sintassi per alias di tipo)
In Python 3.12 è stata introdotta una sintassi dedicata per definire alias di tipo: l'istruzione type. Questo permette ai suggerimenti di tipo di funzionare non solo come informazioni supplementari, ma anche come elemento del linguaggio per esprimere chiaramente l'intento progettuale.
1type UserId = int
2type UserName = str
3
4def greet(user_id: UserId, name: UserName) -> str:
5 return f"Hello, {name} (id={user_id})"- Assegnando un significato a
UserIdoUserName, le differenze di ruolo possono essere chiarite anche se entrambi utilizzano lo stesso tipointostr. - Le definizioni di tipo diventano più concise, riducendo il costo di comprensione durante il code review e la manutenzione.
- In passato, alias di tipo come
UserId = intvenivano creati per assegnazione, ma utilizzando l'istruzionetyperisulta esplicito che 'questa è una definizione di tipo'. Ciò è particolarmente efficace per migliorare la leggibilità del design in code base di medie e grandi dimensioni.
Annotazioni di tipo naturali usando tipi nativi (generici semplificati da Python 3.9+)
Da Python 3.9 è possibile utilizzare direttamente i tipi nativi come list o dict come generici.
Ciò consente di scrivere suggerimenti di tipo intuitivi e leggibili senza importare tipi dal modulo typing.
1def sum_numbers(numbers: list[int]) -> int:
2 return sum(numbers)
3
4print(sum_numbers([1, 2, 3, 4]))- I suggerimenti di tipo funzionano non come 'vincoli', ma come 'documentazione che spiega il contenuto della lavorazione'.
Catena di metodi sicura con il tipo Self (Python 3.11 e successivi)
Da Python 3.11, è possibile specificare Self come tipo di ritorno per i metodi che restituiscono la stessa classe.
Ciò permette di scrivere catene di metodi in modo sicuro senza perdere le informazioni di tipo.
1from typing import Self
2
3class Counter:
4 def __init__(self, value: int = 0) -> None:
5 self.value = value
6
7 def increment(self) -> Self:
8 self.value += 1
9 return self
10
11counter = Counter()
12counter.increment().increment()
13print(counter.value)- Anche per i metodi che restituiscono
self, il tipo di ritorno corretto viene preservato. - IDE e controllori di tipo possono interpretare correttamente la catena dei metodi.
Gestione delle stringhe più chiara (removeprefix / removesuffix | Python 3.9 e successivi)
Da Python 3.9, sono stati aggiunti i metodi specializzati str.removeprefix() e str.removesuffix() per rimuovere in sicurezza prefissi e suffissi da stringhe. Con questi metodi, è possibile esprimere chiaramente l'intento di 'rimuovere solo l'inizio o la fine' nel codice.
1filename = "report_2026.txt"
2
3clean_name = filename.removeprefix("report_")
4name_without_ext = clean_name.removesuffix(".txt")
5
6print(name_without_ext)- La stringa specificata viene rimossa solo se presente all'inizio o alla fine, evitando sostituzioni indesiderate.
- Questo approccio offre maggiore leggibilità e sicurezza rispetto all'utilizzo di
replace()o dello slicing. - In particolare nella gestione di 'stringhe con un formato definito', come nomi di file o preprocessamento di URL, l'uso di questi metodi può ridurre notevolmente il rischio di bug.
Confronto robusto di stringhe per l'internazionalizzazione (str.casefold() | Supporto Unicode)
str.casefold() in Python è un metodo per il confronto insensibile alle maiuscole che tiene conto di Unicode. A differenza di lower() o upper(), normalizza le stringhe includendo conversioni specifiche per la lingua.
1text1 = "Stra\u00dfe"
2text2 = "strasse"
3
4print(text1)
5print(text2)
6
7print(f"Comparison Result: {text1.casefold() == text2.casefold()}")- Può gestire correttamente le differenze dipendenti dalla lingua come la
ßtedesca ess. - Questa è una tecnica essenziale per applicazioni basate su supporto multilingue o internazionalizzazione.
Supporto TOML standard (tomllib | Python 3.11 e successivi)
Da Python 3.11, il modulo tomllib per leggere file di configurazione TOML è stato aggiunto alla libreria standard. La gestione delle configurazioni può ora essere effettuata interamente in Python, senza dipendere da librerie esterne.
1import tomllib
2
3with open("config.toml", "rb") as f:
4 config = tomllib.load(f)
5
6print(config["database"]["host"])
7
8# config.toml
9# title = "TOML Example"
10# [database]
11# host = "192.168.1.1"
12# ports = [ 8001, 8001, 8002 ]- Non sono più necessari pacchetti esterni come
toml, semplificando le dipendenze. - Il caricamento dei file di configurazione è standardizzato, rendendo più semplice la distribuzione, l'operatività e la gestione di ambienti CI.
Gestione delle eccezioni per l'era dell'elaborazione parallela (ExceptionGroup / except* | Python 3.11 e successivi)
Python 3.11 ha introdotto ExceptionGroup per gestire più eccezioni contemporaneamente e la sintassi except* per gestirle in modo sicuro nei rami condizionali. Questa è una nuova funzionalità per gestire 'errori simultanei' che si presentano nell'elaborazione asincrona o parallela.
1def process(values):
2 errors = []
3 for v in values:
4 if v < 0:
5 errors.append(ValueError(f"Negative value: {v}"))
6 if errors:
7 raise ExceptionGroup("Invalid values", errors)
8
9try:
10 process([1, -2, -3])
11except* ValueError as e:
12 print("Handled:", e)- Ora è possibile sollevare e classificare più eccezioni in un'unica operazione.
- Affronta il problema, frequente nell'elaborazione asincrona, in cui era visibile solo il primo errore.
- In operazioni come
asyncio.gather()o processi batch paralleli, più fattori di errore possono verificarsi contemporaneamente. UtilizzandoExceptionGroup, è più facile gestire raccolta degli errori, logging e strategie di retry.
Le prestazioni migliorano semplicemente aggiornando all'ultima versione
Da Python 3.11 molti processi sono stati velocizzati grazie alle ottimizzazioni interne.
1def count_up(n):
2 total = 0
3 for i in range(n):
4 total += i
5 return total
6
7print(count_up(1_000_000))- Un grande vantaggio è che i miglioramenti di velocità si ottengono senza riscrivere il codice.
Controllo della Garbage Collection (Gestione esplicita tramite modulo gc)
In Python, usando il modulo standard gc si può disabilitare temporaneamente o eseguire manualmente la garbage collection. Questa è una tecnica di ottimizzazione efficace in scenari come il trattamento batch di grandi quantità di dati o operazioni critiche dal punto di vista delle prestazioni.
1import gc
2
3gc.disable()
4# heavy batch processing
5gc.enable()
6gc.collect()- Sopprimendo l'attivazione inutile della garbage collection si possono ridurre le fluttuazioni nei tempi di esecuzione.
- Si può eseguire la raccolta esplicitamente a intervalli, rendendo più semplice il monitoraggio dell'utilizzo della memoria.
- Tuttavia, questa tecnica non dovrebbe essere usata di default ma presa in considerazione soltanto se il profiling mostra che la GC è un collo di bottiglia. Per la maggior parte delle applicazioni è più sicuro affidarsi alla garbage collection automatica di Python.
Riepilogo
Con i miglioramenti nei messaggi di errore e l'evoluzione dei suggerimenti di tipo nelle versioni Python 3.12-3.13, comprendere e mantenere il codice è diventato più facile che mai. Inoltre, i miglioramenti come una migliore esperienza di debugging e le ottimizzazioni interne stanno contribuendo direttamente e concretamente alla produttività. Non è necessario usare tutte queste nuove funzionalità contemporaneamente; è pratico iniziare dall'ultima versione di Python e integrare gradualmente le funzionalità necessarie. Questa adozione graduale porta a un codice Python più leggibile e robusto.
Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.