CHI HA PAURA DELL’INTELLIGENZA ARTIFICIALE?
Quando programmiamo, ogni dato che utilizziamo – numeri, stringhe, immagini, strutture complesse – deve essere memorizzato in uno spazio fisico: la memoria RAM. Comprendere come questa viene organizzata e gestita significa entrare nel livello strutturale dell’informatica, dove efficienza, velocità e stabilità del software dipendono da scelte progettuali consapevoli.
La gestione della memoria non è solo un dettaglio tecnico: è uno degli elementi che distingue un codice “che funziona” da un codice robusto, scalabile e performante.
La memoria è uno spazio indirizzabile composto da celle numerate (indirizzi). Ogni cella può contenere una quantità limitata di dati. Quando scriviamo:
x = 5
accadono diverse operazioni invisibili:
5.x diventa un riferimento a quell’oggetto.È importante comprendere che in Python le variabili non contengono direttamente il valore, ma un riferimento a un oggetto memorizzato altrove.
In molti linguaggi la memoria si divide concettualmente in:
Python gestisce automaticamente queste aree, ma internamente utilizza meccanismi simili.
Un intero (int) o un booleano occupano meno memoria rispetto a strutture complesse, ma in Python anche gli interi sono oggetti, quindi hanno un overhead interno (metadati, gestione del tipo, contatore di riferimenti).
Esempio:
a = 10
b = 10
In Python, piccoli interi possono essere condivisi (ottimizzazione interna), quindi a e b possono riferirsi allo stesso oggetto in memoria.
Una lista non contiene direttamente i valori, ma riferimenti agli oggetti.
lista = [1, 2, 3]
In memoria abbiamo:
Questo significa che una lista cresce in modo dinamico e può richiedere riallocazioni di memoria quando aumenta di dimensione.
I dizionari utilizzano tabelle hash. Ogni elemento richiede:
Sono estremamente veloci nelle ricerche, ma consumano più memoria rispetto a una lista equivalente.
Strutture come gli array (ad esempio tramite librerie scientifiche) sono più efficienti perché memorizzano dati omogenei in modo contiguo, riducendo overhead e migliorando la località di memoria.
Ogni oggetto occupa:
Un programma è “pesante” quando:
Esempio inefficiente:
numeri = []
for i in range(1000000):
numeri.append(i)
Se i dati non servono tutti contemporaneamente, una soluzione più efficiente potrebbe essere usare un generatore, che non carica tutto in memoria.
Python utilizza due meccanismi principali:
Ogni oggetto ha un contatore di riferimenti. Quando il contatore scende a zero, l’oggetto viene eliminato.
a = [1, 2, 3]
b = a
del a
L’oggetto non viene eliminato finché b esiste.
Gestisce i riferimenti circolari, cioè oggetti che si riferiscono tra loro impedendo al contatore di scendere a zero.
Esempio concettuale:
a = []
b = []
a.append(b)
b.append(a)
Qui i due oggetti si referenziano reciprocamente.
Python interviene periodicamente per liberare memoria in questi casi.
⚠ Tuttavia, il Garbage Collector non è una soluzione magica: mantenere oggetti inutilizzati rallenta comunque il sistema.
Provocano errori di runtime e indicano cattiva gestione dello stato del programma.
lista = [1,2,3]
lista = 5
Il nome cambia significato, generando potenziali bug logici.
nuova_lista = lista[:]
Se non necessario, questa operazione raddoppia l’uso di memoria.
In Python non sono comuni come in C/C++, ma possono verificarsi quando oggetti restano referenziati senza necessità.
yield) per grandi sequenzedel)Utilizzare strumenti didattici come:
Osservare:
Obiettivo: sviluppare consapevolezza visiva dei meccanismi interni.
Confrontare:
Versione inefficiente
lista = [i for i in range(1000000)]
somma = sum(lista)
Versione ottimizzata
somma = sum(i for i in range(1000000))
Misurare:
Progetto: analizzatore di dati numerici
Obiettivo:
Soluzione efficiente:
La gestione della memoria è il punto di incontro tra teoria dell’informazione, architettura dei calcolatori e qualità del software.
Comprendere:
significa scrivere programmi più veloci, più puliti e più professionali.
Un buon programmatore non pensa solo a “far funzionare” il codice: pensa a come occupa lo spazio, quanto consuma e quanto può scalare nel tempo.
1. Cosa fa la garbage collection in Python?
2. Cosa succede se usi una variabile non inizializzata?
3. Quale delle seguenti strutture occupa in genere più memoria?
Punteggio: 0/3
Commenti
Posta un commento