■ PYTHON
Guida Completa alla Programmazione
Dalle basi assolute alla programmazione avanzata: sintassi,
strutture dati, funzioni, OOP, librerie essenziali e progetti reali
Linguaggio Python 3.10+
Livello Zero → Intermedio/Avanzato
Sezioni Sintassi, Strutture dati, Funzioni, OOP, Librerie, Progetti
1. Cos'è Python e perché impararlo
Python è un linguaggio di programmazione ad alto livello, interpretato e a tipizzazione dinamica,
creato da Guido van Rossum nel 1991. È oggi il linguaggio più popolare al mondo secondo l'indice
TIOBE e Stack Overflow Developer Survey. La sua filosofia si basa sulla leggibilità del codice e sulla
produttività dello sviluppatore: 'dovrebbe esserci un modo ovvio per fare ogni cosa'.
Perché scegliere Python?
• Sintassi pulita e leggibile: codice che si legge quasi come l'italiano
• Versatilità totale: web, AI/ML, data science, automazione, scripting, IoT
• Ecosistema enorme: oltre 450.000 pacchetti su PyPI (il repository ufficiale)
• Community vastissima: documentazione, tutorial, forum disponibili per ogni problema
• Alta domanda lavorativa: tra i linguaggi più richiesti nel mercato del lavoro tech
• Ottimo per i principianti: curva di apprendimento morbida e feedback immediato
• Usato da Google, Netflix, Instagram, Spotify, NASA, OpenAI
1.1 Installazione di Python
# Installazione e verifica
# 1. Scarica Python da [Link]
# 2. Durante l'installazione: spunta 'Add Python to PATH'
# 3. Verifica nel terminale:
python --version # oppure: python3 --version
# Output atteso:
Python 3.12.0
# 4. Installa pip (gestore pacchetti) - di solito già incluso:
pip --version
# 5. IDE consigliati:
# - VS Code (gratuito, leggero, estensioni Python eccellenti)
# - PyCharm Community (gratuito, dedicato a Python)
# - Jupyter Notebook (ottimo per data science e apprendimento)
2. Sintassi Base di Python
2.1 Variabili e Tipi di Dati
In Python non devi dichiarare il tipo di una variabile: viene inferito automaticamente dall'interprete
(tipizzazione dinamica). Puoi cambiare il tipo di una variabile in qualsiasi momento.
# Variabili e tipi di dati
# Interi (int)
eta = 25
anno = 2024
# Decimali (float)
prezzo = 19.99
pi = 3.14159
# Stringhe (str)
nome = 'Mario'
cognome = "Rossi"
frase = f"Ciao, mi chiamo {nome} {cognome}!" # f-string
# Booleani (bool)
attivo = True
admin = False
# Verifica il tipo
print(type(eta)) #
print(type(prezzo)) #
print(type(nome)) #
# Conversione di tipo (casting)
numero_str = '42'
numero_int = int(numero_str) # '42' → 42
numero_float = float('3.14') # '3.14' → 3.14
testo = str(100) # 100 → '100'
2.2 Operatori
Op Nome Esempio Op Nome Esempio
+ Addizione 5 + 3 = 8 - Sottrazione 10 - 4 = 6
Moltiplicazion
* 3 * 4 = 12 / Divisione 10 / 3 = 3.33
e
Divisione
// 10 // 3 = 3 % Modulo (resto) 10 % 3 = 1
intera
** Potenza 2 ** 8 = 256 == Uguale a 5 == 5 → True
Maggiore/Minor
!= Diverso da 3 != 5 → True >/< 5 > 3 → True
e
True and False True or False →
and E logico or O logico
→ False True
not True → 'a' in 'ciao' →
not Negazione in Appartiene a
False True
3. Strutture di Controllo del Flusso
3.1 Condizionali (if / elif / else)
Python usa l'indentazione (4 spazi o 1 tab) per definire i blocchi di codice, NON le parentesi graffe
come in altri linguaggi. È cruciale mantenere l'indentazione coerente o il codice darà errore.
# Struttura if-elif-else
voto = 85
if voto >= 90:
print('Ottimo! Lode meritata')
elif voto >= 75:
print('Molto bene!')
elif voto >= 60:
print('Sufficiente')
else:
print('Insufficiente, riprova')
# Output: Molto bene!
# Operatore ternario (una riga)
status = 'maggiorenne' if voto >= 18 else 'minorenne'
# match-case (Python 3.10+) — come switch in altri linguaggi
comando = 'start'
match comando:
case 'start':
print('Avvio...')
case 'stop':
print('Stop.')
case _:
print('Comando non riconosciuto')
3.2 Cicli: for e while
# Ciclo for — iterazione su sequenze
# Iterare su una lista
frutti = ['mela', 'banana', 'arancia']
for frutto in frutti:
print(f'Frutto: {frutto}')
# range(): genera sequenze numeriche
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(1, 11): # 1, 2, ..., 10
print(i)
for i in range(0, 20, 2): # 0, 2, 4, 6, ..., 18 (step 2)
print(i)
# enumerate(): indice + valore
for indice, valore in enumerate(frutti):
print(f'{indice}: {valore}')
# zip(): itera su più liste in parallelo
nomi = ['Alice', 'Bob', 'Carlo']
voti = [90, 75, 88]
for nome, voto in zip(nomi, voti):
print(f'{nome}: {voto}')
# Ciclo while — ripeti finché condizione è vera
contatore = 0
while contatore < 5:
print(f'Contatore: {contatore}')
contatore += 1 # equivale a: contatore = contatore + 1
# break: esce dal ciclo
# continue: salta all'iterazione successiva
for i in range(10):
if i == 3:
continue # salta il 3
if i == 7:
break # ferma il ciclo a 7
print(i) # stampa: 0 1 2 4 5 6
4. Strutture Dati Fondamentali
Python ha quattro strutture dati built-in principali: Liste, Tuple, Dizionari e Set. Scegliere quella giusta
per ogni situazione è fondamentale per scrivere codice efficiente.
Struttura Sintassi Mutabile Ordinata Uso tipico
Lista (list) [] ■ Sì ■ Sì Collezione ordinata e modificabile
Tupla (tuple) () ■ No ■ Sì Dati fissi, coordinate, record
Dizionario (dict) { k:v } ■ Sì ■ Sì* Mappatura chiave→valore
Set (set) {} ■ Sì ■ No Unicità, operazioni insiemistiche
# Liste — operazioni essenziali
numeri = [1, 2, 3, 4, 5]
# Accesso per indice (0-based)
print(numeri[0]) # 1 (primo elemento)
print(numeri[-1]) # 5 (ultimo elemento)
print(numeri[1:3]) # [2, 3] (slicing)
# Modifica
[Link](6) # aggiunge in fondo: [1,2,3,4,5,6]
[Link](0, 0) # inserisce in pos. 0: [0,1,2,3,4,5,6]
[Link](3) # rimuove il valore 3
estratto = [Link]() # rimuove e restituisce l'ultimo
# Operazioni utili
print(len(numeri)) # lunghezza
print(sorted(numeri)) # ordina (restituisce nuova lista)
[Link](reverse=True) # ordina in-place al contrario
print(sum(numeri)) # somma
print(min(numeri), max(numeri))
# List comprehension — crea liste in una riga
quadrati = [x**2 for x in range(1, 11)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
pari = [x for x in range(20) if x % 2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# Dizionari — la struttura più usata in Python
persona = {
'nome': 'Alice',
'eta': 30,
'citta': 'Milano',
'professione': 'Developer'
# Accesso
print(persona['nome']) # Alice
print([Link]('eta', 0)) # 30 (get evita KeyError)
# Modifica e aggiunta
persona['eta'] = 31 # modifica valore esistente
persona['email'] = 'alice@[Link]' # aggiunge nuova chiave
# Iterazione
for chiave, valore in [Link]():
print(f'{chiave}: {valore}')
# Controllo esistenza
if 'nome' in persona:
print('La chiave nome esiste')
# Dict comprehension
quadrati_dict = {x: x**2 for x in range(1, 6)}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
5. Funzioni in Python
Le funzioni sono il blocco fondamentale di organizzazione del codice. In Python si definiscono con la
keyword 'def'. Una buona funzione fa UNA sola cosa, ha un nome descrittivo e include una docstring
che spiega cosa fa.
# Definizione e uso delle funzioni
# Funzione base
def saluta(nome):
'''Stampa un messaggio di saluto personalizzato'''
print(f'Ciao, {nome}!')
saluta('Mario') # Ciao, Mario!
# Funzione con valore di ritorno
def somma(a, b):
'''Restituisce la somma di due numeri'''
return a + b
risultato = somma(10, 25) # risultato = 35
# Parametri con valore di default
def potenza(base, esponente=2):
return base ** esponente
print(potenza(5)) # 25 (usa default esponente=2)
print(potenza(2, 10)) # 1024
# Argomenti keyword (ordine libero)
def descrivi_persona(nome, eta, citta):
return f'{nome}, {eta} anni, vive a {citta}'
print(descrivi_persona(eta=25, citta='Roma', nome='Luca'))
# *args: numero variabile di argomenti
def somma_tutti(*numeri):
return sum(numeri)
print(somma_tutti(1, 2, 3, 4, 5)) # 15
# **kwargs: argomenti keyword variabili
def profilo(**dati):
for chiave, valore in [Link]():
print(f'{chiave}: {valore}')
profilo(nome='Sara', eta=28, hobby='coding')
# Lambda, map, filter — programmazione funzionale
# Lambda: funzione anonima in una riga
quadrato = lambda x: x ** 2
print(quadrato(7)) # 49
# Utile per ordinamento custom
persone = [('Alice', 30), ('Bob', 25), ('Carlo', 35)]
[Link](key=lambda p: p[1]) # ordina per età
# map(): applica una funzione a ogni elemento
numeri = [1, 2, 3, 4, 5]
quadrati = list(map(lambda x: x**2, numeri))
# [1, 4, 9, 16, 25]
# filter(): filtra elementi in base a condizione
pari = list(filter(lambda x: x % 2 == 0, numeri))
# [2, 4]
# Equivalenti con list comprehension (stile più pythonic):
quadrati = [x**2 for x in numeri]
pari = [x for x in numeri if x % 2 == 0]
6. Programmazione Orientata agli Oggetti
(OOP)
La OOP è un paradigma che organizza il codice intorno a 'oggetti' — entità che combinano dati
(attributi) e comportamenti (metodi). Python è un linguaggio pienamente orientato agli oggetti: tutto in
Python è un oggetto.
I 4 pilastri della OOP:
• Incapsulamento: nasconde i dati interni e li espone solo tramite metodi
• Ereditarietà: una classe può estendere un'altra riutilizzando il suo codice
• Polimorfismo: oggetti di classi diverse possono rispondere allo stesso metodo
• Astrazione: nasconde i dettagli complessi dietro un'interfaccia semplice
# Definizione di una classe completa
class Conto:
'''Rappresenta un conto bancario'''
tasso_interesse = 0.02 # attributo di classe (condiviso)
def __init__(self, titolare, saldo_iniziale=0):
'''Costruttore: inizializza il conto'''
[Link] = titolare # attributo di istanza
self._saldo = saldo_iniziale # _ = convenzione 'privato'
self._transazioni = []
@property
def saldo(self):
'''Getter: accede al saldo come se fosse un attributo'''
return self._saldo
def deposita(self, importo):
if importo > 0:
self._saldo += importo
self._transazioni.append(f'+{importo}')
return True
return False
def preleva(self, importo):
if 0 < importo <= self._saldo:
self._saldo -= importo
self._transazioni.append(f'-{importo}')
return True
print('Fondi insufficienti')
return False
def __str__(self):
'''Rappresentazione testuale dell'oggetto'''
return f'Conto di {[Link]}: €{self._saldo:.2f}'
def __repr__(self):
return f'Conto(titolare={[Link]!r}, saldo={self._saldo})'
# Uso della classe
mio_conto = Conto('Alice', 1000)
mio_conto.deposita(500)
mio_conto.preleva(200)
print(mio_conto) # Conto di Alice: €1300.00
print(mio_conto.saldo) # 1300
# Ereditarietà — estendere una classe
class ContoRisparmio(Conto): # ContoRisparmio eredita da Conto
def __init__(self, titolare, saldo_iniziale=0, tasso=0.03):
super().__init__(titolare, saldo_iniziale) # chiama __init__ del padre
[Link] = tasso
def applica_interessi(self):
'''Metodo aggiuntivo non presente nella classe padre'''
interessi = self._saldo * [Link]
[Link](interessi)
print(f'Interessi applicati: +€{interessi:.2f}')
def __str__(self): # override del metodo padre
return f'[Risparmio] {super().__str__()} | Tasso: {[Link]*100}%'
risparmio = ContoRisparmio('Bob', 5000, tasso=0.04)
risparmio.applica_interessi() # Interessi applicati: +€200.00
print(risparmio) # [Risparmio] Conto di Bob: €5200.00 | Tasso: 4.0%
# isinstance() verifica il tipo
print(isinstance(risparmio, ContoRisparmio)) # True
print(isinstance(risparmio, Conto)) # True (eredita!)
7. Gestione degli Errori ed Eccezioni
In Python gli errori a runtime si chiamano Eccezioni. Gestirle correttamente rende il codice robusto e
user-friendly. Si usa il blocco try/except/else/finally.
# Gestione eccezioni — try/except/finally
# Struttura base
try:
numero = int(input('Inserisci un numero: '))
risultato = 100 / numero
print(f'Risultato: {risultato}')
except ValueError:
print('Errore: devi inserire un numero intero')
except ZeroDivisionError:
print('Errore: divisione per zero non permessa')
except Exception as e:
print(f'Errore imprevisto: {e}') # cattura qualsiasi errore
else:
print('Operazione completata con successo') # solo se no errori
finally:
print('Questo blocco esegue SEMPRE') # cleanup
# Eccezioni personalizzate
class SaldoInsufficienteError(Exception):
def __init__(self, saldo, importo):
[Link] = saldo
[Link] = importo
super().__init__(f'Saldo {saldo}€ insufficiente per prelievo {importo}€')
def preleva_sicuro(saldo, importo):
if importo > saldo:
raise SaldoInsufficienteError(saldo, importo)
return saldo - importo
try:
preleva_sicuro(100, 200)
except SaldoInsufficienteError as e:
print(e) # Saldo 100€ insufficiente per prelievo 200€
8. File I/O, Moduli e Librerie
# Lettura e scrittura di file
# Scrittura su file (crea o sovrascrive)
with open('[Link]', 'w', encoding='utf-8') as f:
[Link]('Prima riga\n')
[Link]('Seconda riga\n')
# Lettura completa
with open('[Link]', 'r', encoding='utf-8') as f:
contenuto = [Link]()
print(contenuto)
# Lettura riga per riga (efficiente per file grandi)
with open('[Link]', 'r', encoding='utf-8') as f:
for riga in f:
print([Link]()) # strip() rimuove \n finale
# Aggiunta in fondo al file (append)
with open('[Link]', 'a', encoding='utf-8') as f:
[Link]('Terza riga aggiunta\n')
# JSON: salvare e caricare strutture dati
import json
dati = {'nome': 'Alice', 'voti': [90, 85, 92]}
with open('[Link]', 'w') as f:
[Link](dati, f, indent=2)
with open('[Link]', 'r') as f:
caricato = [Link](f)
print(caricato['nome']) # Alice
8.2 Librerie Essenziali della Standard Library
Modulo Descrizione
os / pathlib Gestione file e directory, percorsi, variabili ambiente
sys Argomenti da linea di comando, informazioni sull'interprete
datetime Date, orari, differenze temporali, formattazione
math / statistics Funzioni matematiche avanzate, media, deviazione standard
random Numeri casuali, shuffle liste, scelta casuale
re Espressioni regolari per pattern matching nei testi
collections Counter, defaultdict, deque, namedtuple — strutture dati avanzate
itertools Strumenti per iterazione: combinazioni, permutazioni, prodotto cartesiano
json / csv Lettura e scrittura di file JSON e CSV
urllib /
Richieste HTTP base (meglio usare requests esternamente)
[Link]
threading /
Esecuzione parallela e concorrente
multiprocessing
logging Sistema di logging professionale (meglio di print() per debug)
9. Librerie Esterne Fondamentali
Libreria Installazione Uso principale
HTTP requests semplici — API REST, web scraping
requests pip install requests
base
Array N-dimensionali, operazioni matematiche
numpy pip install numpy
vettorizzate
pandas pip install pandas Analisi dati con DataFrame — il 'Excel' di Python
matplotlib pip install matplotlib Grafici e visualizzazioni dati 2D
seaborn pip install seaborn Grafici statistici belli su base matplotlib
pip install Machine Learning: classificazione, regressione,
scikit-learn
scikit-learn clustering
tensorflow /
pip install tensorflow Deep Learning, reti neurali, AI avanzata
torch
flask pip install flask Web framework leggero — API e siti web semplici
Web framework completo — applicazioni web
django pip install django
complesse
fastapi pip install fastapi API REST moderne ad alta performance con type hints
ORM per database relazionali (PostgreSQL, MySQL,
sqlalchemy pip install sqlalchemy
SQLite)
beautifulsou pip install
Web scraping — parsing HTML e XML
p4 beautifulsoup4
pytest pip install pytest Framework di testing — test automatizzati professionali
pydantic pip install pydantic Validazione dati e serializzazione con type hints
10. Progetto Pratico: Gestore di Contatti
Mettiamo insieme tutto ciò che abbiamo imparato in un progetto reale: un'applicazione a riga di
comando per gestire una rubrica di contatti, con salvataggio su file JSON.
# [Link] — Progetto completo
import json
import os
FILE_RUBRICA = '[Link]'
class Contatto:
def __init__(self, nome, telefono, email=''):
[Link] = nome
[Link] = telefono
[Link] = email
def to_dict(self):
return {'nome': [Link], 'telefono': [Link], 'email': [Link]}
@classmethod
def from_dict(cls, dati):
return cls(dati['nome'], dati['telefono'], [Link]('email', ''))
def __str__(self):
return f'{[Link]} | Tel: {[Link]} | Email: {[Link] or "-"}'
def carica_rubrica():
if not [Link](FILE_RUBRICA):
return []
with open(FILE_RUBRICA, 'r', encoding='utf-8') as f:
return [Contatto.from_dict(c) for c in [Link](f)]
def salva_rubrica(contatti):
with open(FILE_RUBRICA, 'w', encoding='utf-8') as f:
[Link]([c.to_dict() for c in contatti], f, indent=2, ensure_ascii=False)
def aggiungi_contatto(rubrica):
nome = input('Nome: ').strip()
telefono = input('Telefono: ').strip()
email = input('Email (opzionale): ').strip()
[Link](Contatto(nome, telefono, email))
salva_rubrica(rubrica)
print(f'Contatto {nome} aggiunto!')
def cerca_contatto(rubrica):
query = input('Cerca per nome: ').lower()
trovati = [c for c in rubrica if query in [Link]()]
if trovati:
for c in trovati: print(c)
else:
print('Nessun contatto trovato')
def main():
rubrica = carica_rubrica()
while True:
print('\n=== RUBRICA === [Link] [Link] [Link] [Link]')
scelta = input('Scelta: ')
if scelta == '1':
for c in rubrica: print(c)
elif scelta == '2': aggiungi_contatto(rubrica)
elif scelta == '3': cerca_contatto(rubrica)
elif scelta == '4': break
if __name__ == '__main__':
main()
11. Best Practice e Stile Python (PEP 8)
✦ Nomi descrittivi: usa nomi_con_underscore per variabili/funzioni, NomeCamelCase per classi
✦ Funzioni brevi: ogni funzione fa una cosa sola e la fa bene (principio SRP)
✦ Docstring sempre: documenta ogni funzione, classe e modulo con stringhe triple
✦ Commenti utili: spiega PERCHÉ, non COSA (il codice deve parlare da solo per il cosa)
✦ Gestisci le eccezioni: mai lasciare un except vuoto o che cattura tutto in silenzio
✦ Virtual environment: usa venv per isolare le dipendenze di ogni progetto
✦ [Link]: documenta le dipendenze con 'pip freeze > [Link]'
✦ Type hints: aggiungi annotazioni di tipo per codice più leggibile e manutenibile
✦ Test automatici: scrivi test con pytest — almeno per le funzioni critiche
✦ Linting: usa flake8 o ruff per trovare errori di stile, black per formattare automaticamente
✦ Version control: usa Git per tracciare tutte le modifiche al codice
✦ DRY (Don't Repeat Yourself): se copi-incolli codice, probabilmente serve una funzione
# Esempio di codice Pythonic vs non-Pythonic
# ■ NON Pythonic
i = 0
while i < len(lista):
print(lista[i])
i += 1
# ■ Pythonic
for elemento in lista:
print(elemento)
# ■ NON Pythonic
if len(lista) > 0:
processa(lista)
# ■ Pythonic (liste vuote sono falsy)
if lista:
processa(lista)
# ■ NON Pythonic
risultato = []
for x in numeri:
if x > 0:
[Link](x * 2)
# ■ Pythonic (list comprehension)
risultato = [x * 2 for x in numeri if x > 0]
Python è un linguaggio che premia la semplicità e la chiarezza. Approfondisci con la documentazione ufficiale
su [Link], il corso gratuito su Real Python ([Link]) e praticate ogni giorno su LeetCode o
HackerRank per solidificare le basi algoritmiche.