Davanti a un editor vuoto, la difficoltà non è ricordare la sintassi, ma capire quale problema risolvere per primo. In questa guida raccolgo esercizi Python progressivi, con esempi su condizioni, cicli, funzioni, strutture dati e database SQLite, così puoi trasformare la teoria in programmi piccoli ma utili.
Un percorso pratico per imparare Python scrivendo codice
- Parti dalle basi con input, condizioni, cicli e funzioni semplici.
- Aumenta la difficoltà gradualmente introducendo liste, dizionari, file ed errori.
- Risolvi prima il problema, poi confronta il tuo codice con una soluzione alternativa.
- Usa i test per verificare casi normali, valori limite e input non validi.
- Collega Python a SQLite per passare dalla logica degli esercizi a un piccolo progetto reale.
Da dove partire senza perdersi nella sintassi
Per imparare davvero, io preferisco esercizi brevi con un obiettivo preciso. Un programma che calcola il prezzo finale o conta le parole sembra elementare, ma costringe a usare variabili, operatori, condizioni e funzioni in un contesto concreto.
La progressione conta più della quantità. Saltare subito a classi, framework o intelligenza artificiale spesso crea l’illusione di lavorare su progetti importanti, mentre restano fragili concetti fondamentali come il controllo del flusso e la gestione degli errori.
| Livello | Argomenti | Obiettivo pratico |
|---|---|---|
| Base | Variabili, input, condizioni, cicli | Scrivere programmi lineari e prevedibili |
| Intermedio | Funzioni, liste, dizionari, stringhe | Dividere il codice e lavorare su dati reali |
| Applicato | File, eccezioni, SQLite, test | Costruire piccoli strumenti riutilizzabili |
Per ogni esercizio suggerisco di lavorare in tre passaggi. Prima scrivo la traccia con parole mie, poi preparo una soluzione minima e infine aggiungo casi di prova. Questo metodo fa emergere gli errori di ragionamento molto prima dei problemi di sintassi.
Tre esercizi fondamentali per iniziare
Calcolare il prezzo con uno sconto
Chiedi all’utente il prezzo di un prodotto e la percentuale di sconto. Il programma deve restituire il prezzo finale, impedendo valori negativi o percentuali superiori a 100.
prezzo = float(input("Prezzo: "))
sconto = float(input("Sconto percentuale: "))
if prezzo < 0 or sconto < 0 or sconto > 100:
print("Inserisci valori validi")
else:
finale = prezzo * (1 - sconto / 100)
print(f"Prezzo finale: {finale:.2f} euro")L’esercizio sembra matematico, ma insegna una cosa essenziale: validare l’input prima di usarlo. Il formato :.2f serve invece a mostrare due cifre decimali, una scelta piccola ma importante quando si lavora con importi.
Contare numeri pari e dispari
Chiedi una serie di numeri separati da virgola e conta quanti sono pari e quanti dispari. La funzione split() divide il testo, mentre l’operatore modulo % restituisce il resto della divisione.
testo = input("Inserisci numeri separati da virgola: ")
numeri = [int valore.strip() for valore in testo.split(",")]
pari = 0
dispari = 0
for numero in numeri:
if numero % 2 == 0:
pari += 1
else:
dispari += 1
print(f"Pari: {pari}")
print(f"Dispari: {dispari}")Nell’esempio c’è un errore intenzionale nella comprensione della sintassi. La forma corretta è questa:
numeri = [int(valore.strip()) for valore in testo.split(",")]Questo è un buon esercizio anche per imparare a leggere gli errori dell’interprete. Python indica la riga problematica, ma sta a noi capire se manca una parentesi, se il tipo è sbagliato o se l’input non rispetta il formato atteso.
Creare una funzione per la temperatura
Scrivi una funzione che converta i gradi Celsius in Fahrenheit e un’altra che faccia il contrario. La formula è semplice, ma separare il calcolo dalla stampa abitua a costruire codice più facile da testare.
def celsius_a_fahrenheit(celsius):
return celsius * 9 / 5 + 32
def fahrenheit_a_celsius(fahrenheit):
return (fahrenheit - 32) * 5 / 9
print(celsius_a_fahrenheit(20))
print(fahrenheit_a_celsius(68))Io considero le funzioni il primo vero salto di qualità. Una funzione dovrebbe occuparsi di un compito riconoscibile e restituire un risultato, senza mescolare calcoli, input e messaggi a video quando non è necessario.
Come allenare liste, stringhe e dizionari
Quando le basi sono abbastanza solide, gli esercizi devono iniziare a manipolare dati. Liste, stringhe e dizionari sono gli strumenti che userai più spesso per rappresentare prodotti, utenti, ordini, risultati o righe importate da un file.
Analizzare una frase
Chiedi una frase e calcola il numero di parole, la parola più lunga e la frequenza di ogni termine. Prima di contare, converti tutto in minuscolo e rimuovi la punteggiatura più comune.
import string
frase = input("Scrivi una frase: ").lower()
pulita = frase.translate(str.maketrans("", "", string.punctuation))
parole = pulita.split()
frequenze = {}
for parola in parole:
frequenze[parola] = frequenze.get(parola, 0) + 1
print(f"Parole totali: {len(parole)}")
if parole:
print(f"Parola più lunga: {max(parole, key=len)}")
print(f"Frequenze: {frequenze}")Qui il dizionario funziona come una piccola tabella chiave-valore. Il metodo get() permette di partire da zero quando una parola compare per la prima volta, evitando un controllo separato con if.
Gestire una lista di prodotti
Rappresenta ogni prodotto con un dizionario contenente nome, prezzo e quantità. Calcola il valore totale del magazzino e mostra solo i prodotti con quantità inferiore a una soglia.
prodotti = [
{"nome": "Tastiera", "prezzo": 49.90, "quantita": 3},
{"nome": "Mouse", "prezzo": 19.90, "quantita": 12},
{"nome": "Monitor", "prezzo": 179.00, "quantita": 2}
]
totale = sum(
prodotto["prezzo"] * prodotto["quantita"]
for prodotto in prodotti
)
sotto_scorta = [
prodotto["nome"]
for prodotto in prodotti
if prodotto["quantita"] < 5
]
print(f"Valore magazzino: {totale:.2f} euro")
print(f"Da riordinare: {sotto_scorta}")Il punto non è imparare a memoria una list comprehension. Prima scriverei lo stesso algoritmo con un ciclo tradizionale, poi confronterei le due versioni. La forma compatta è utile quando resta leggibile, ma la chiarezza viene prima della brevità.
Aggiungere i casi limite
Un esercizio è incompleto se funziona soltanto con l’esempio perfetto. Prova anche una lista vuota, una quantità uguale a zero, prezzi negativi e prodotti con lo stesso nome.
- Una lista vuota non deve causare un errore con
max(). - Un prezzo negativo deve essere rifiutato o segnalato.
- Una quantità pari a zero può essere valida, ma non contribuisce al valore totale.
- Due prodotti con lo stesso nome richiedono una scelta precisa, come sommarli o mantenerli separati.
Questi controlli distinguono un esercizio scolastico da un programma utilizzabile. Nella pratica, gli errori arrivano quasi sempre dai dati inattesi, non dalla riga principale che avevamo immaginato.

Il passaggio dalla logica a un piccolo progetto
Dopo liste e dizionari, il passo naturale è salvare i dati. SQLite è adatto per esercitarsi perché è incluso nella libreria standard di Python e conserva le informazioni in un singolo file, senza richiedere un server separato.
Creare una tabella e inserire dati
Immagina di voler registrare le spese mensili. Il programma seguente crea un database, una tabella e alcune righe. Il simbolo ? nelle query è un parametro, utile per separare i dati dal comando SQL.
import sqlite3
connessione = sqlite3.connect("spese.db")
cursore = connessione.cursor()
cursore.execute("""
CREATE TABLE IF NOT EXISTS spese (
id INTEGER PRIMARY KEY AUTOINCREMENT,
descrizione TEXT NOT NULL,
importo REAL NOT NULL,
categoria TEXT NOT NULL
)
""")
cursore.execute(
"INSERT INTO spese (descrizione, importo, categoria) VALUES (?, ?, ?)",
("Abbonamento software", 29.90, "Lavoro")
)
connessione.commit()
connessione.close()Il metodo commit() rende persistenti le modifiche. Dimenticarlo è uno degli errori più comuni quando si inizia con SQLite, perché il programma può terminare senza mostrare problemi evidenti ma perdere l’inserimento.
Leggi anche: Interfaccia grafica Python - quale toolkit scegliere?
Leggere e aggregare i risultati
Ora puoi calcolare quanto hai speso per categoria. Questo esercizio introduce GROUP BY, una clausola SQL che raggruppa le righe con lo stesso valore.
import sqlite3
with sqlite3.connect("spese.db") as connessione:
risultati = connessione.execute("""
SELECT categoria, SUM(importo)
FROM spese
GROUP BY categoria
ORDER BY SUM(importo) DESC
""")
for categoria, totale in risultati:
print(f"{categoria}: {totale:.2f} euro")La struttura with aiuta a chiudere la connessione anche quando si verifica un problema. In un progetto reale aggiungerei controlli su importi negativi, categorie vuote e valori numerici non validi, perché il database non dovrebbe diventare un deposito di dati incoerenti.
Questo tipo di esercizio è particolarmente utile per chi studia programmazione e database insieme. Python gestisce il flusso dell’applicazione, mentre SQL si occupa di filtrare, raggruppare e aggregare i dati.
Come verificare le soluzioni senza copiare
Quando rimani bloccato, non cercare subito il codice completo. Scrivi prima un esempio piccolo su carta, stampa il valore delle variabili principali e prova a isolare la funzione che non produce il risultato atteso.
Per ogni esercizio preparo almeno quattro prove:
- caso normale, con dati semplici e validi;
- valore limite, come zero, lista vuota o sconto del 100%;
- input errato, per verificare la gestione delle eccezioni;
- caso più grande, per capire se l’algoritmo resta ragionevole.
Per esempio, una funzione che divide due numeri deve stabilire cosa fare quando il divisore è zero. Una soluzione robusta può restituire un messaggio controllato oppure sollevare un’eccezione, ma non dovrebbe lasciare che il comportamento sia casuale o non documentato.
def dividi(a, b):
if b == 0:
raise ValueError("Il divisore non può essere zero")
return a / bQuando il programma cresce, puoi usare assert o il modulo unittest. Non servono decine di test per un esercizio breve: tre o quattro casi ben scelti sono spesso più utili di una lunga lista di esempi simili.
Gli errori che rallentano di più l’apprendimento
Il primo errore è concentrarsi sul risultato e ignorare il percorso. Copiare una soluzione corretta può far superare un esercizio, ma non insegna a riconoscere il tipo di dato, scomporre il problema o scegliere una struttura adeguata.
Un altro problema frequente è usare subito strumenti avanzati. Una libreria può risolvere il compito in una riga, ma se non sai spiegare cosa accade ai dati prima e dopo quella riga, l’esercizio non ha ancora raggiunto il suo scopo.
- Non mescolare tutto in un unico blocco di codice.
- Non usare variabili con nomi vaghi come
xodati2quando il significato è importante. - Non ignorare i messaggi di errore: leggili dal basso verso l’alto e individua la prima riga del tuo programma.
- Non ottimizzare prima di avere una soluzione corretta e leggibile.
La mia regola è semplice: dopo aver risolto un esercizio, lo riscrivo una volta migliorando nomi, funzioni e controlli. Questa seconda versione spesso insegna più della prima, perché trasforma un codice appena funzionante in qualcosa che un’altra persona può capire.
Un percorso concreto per le prossime settimane
Puoi organizzare la pratica in sessioni da 30-45 minuti. Nei primi giorni lavora su input, condizioni e cicli; poi dedica alcuni giorni a stringhe, liste e dizionari; infine costruisci un piccolo progetto con file o SQLite.
Non serve risolvere decine di problemi identici. È più produttivo affrontare da 8 a 12 esercizi diversi, riscriverne alcuni con funzioni migliori e aggiungere test ai casi che inizialmente avevi trascurato.
Quando una traccia diventa troppo facile, aggiungi un vincolo: niente variabili globali, gestione degli errori, dati letti da file, ordinamento o persistenza su database. È così che un esercizio smette di essere un rompicapo isolato e diventa allenamento per problemi che incontrerai davvero.
Il risultato migliore non è una soluzione elegante al primo tentativo, ma la capacità di spiegare perché il programma funziona, dove potrebbe rompersi e come modificarlo senza riscriverlo da zero. Con questa abitudine, ogni nuovo esercizio diventa un passo concreto verso programmi Python più affidabili.