1. Home
  2. iThink
  3. Programmazione per Ragazzi
  4. Liste e dizionari in Python con esempi pratici
Programmazione per Ragazzi Divento Programmatore · Capitolo 5

Liste e dizionari in Python con esempi pratici

Codice Python sullo schermo di un computer
Foto: JohnsonMartin · Pixabay · Licenza dei contenuti Pixabay

Divento Programmatore — Capitolo 5: Liste e dizionari

Finora abbiamo gestito un valore per variabile. Nei giochi serve di più: inventari (10+ oggetti), high-score (lista ordinata), mappe (coordinate → contenuto). Servono collezioni.

Cosa imparerai

| Struttura | Ordinata? | Accesso | Uso tipico | | --- | --- | --- | --- | | Lista (list) | Sì | Indice numerico [] | Sequenze, code, pile, high-score | | Dizionario (dict) | No (da Py 3.7+ mantiene inserimento) | Chiave [] | Mapping, configurazioni, stato entità |


1. Liste: sequenze ordinate mutabili

Creazione di una lista

vuota = []
numeri = [1, 2, 3, 4, 5]
mista = [1, "ciao", 3.14, True, [1, 2]]  # Qualsiasi tipo, anche liste
da_stringa = list("Python")  # ['P', 'y', 't', 'h', 'o', 'n']
da_range = list(range(1, 6)) # [1, 2, 3, 4, 5]

Indexing (indici 0-based)

colori = ["rosso", "verde", "blu", "giallo"]

print(colori[0])   # rosso (primo)
print(colori[1])   # verde
print(colori[-1])  # giallo (ultimo)
print(colori[-2])  # blu (penultimo)

Errore: IndexError se indice fuori range.

Slicing: estrai sotto-liste

numeri = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

numeri[2:5]      # [2, 3, 4]     da 2 (incluso) a 5 (escluso)
numeri[:3]       # [0, 1, 2]     primi 3
numeri[5:]       # [5, 6, 7, 8, 9] da 5 alla fine
numeri[:]        # [0...9]       copia completa
numeri[::2]      # [0, 2, 4, 6, 8] step 2 (pari)
numeri[1::2]     # [1, 3, 5, 7, 9] step 2 da 1 (dispari)
numeri[::-1]     # [9...0]       **inverso!**

Metodi principali (mutano la lista)

| Metodo | Esempio | Effetto | Restituisce | | -------- | --------- | --------- | ------------- | | append(x) | lst.append(9) | Aggiunge in fondo | None | | insert(i, x) | lst.insert(0, "primo") | Inserisce all'indice | None | | extend(iter) | lst.extend([7,8]) | Aggiunge elementi iterabile | None | | pop([i]) | x = lst.pop() / lst.pop(0) | Rimuove e restituisce (default ultimo) | Elemento rimosso | | remove(x) | lst.remove("a") | Rimuove prima occorrenza di x | None | | clear() | lst.clear() | Svuota tutto | None | | index(x) | i = lst.index("a") | Indice prima occorrenza | int | | count(x) | n = lst.count("a") | Quante volte appare x | int | | sort() | lst.sort() / lst.sort(reverse=True) | Ordina in place | None | | reverse() | lst.reverse() | Inverte in place | None | | copy() | nuova = lst.copy() | Copia superficiale | Nuova lista |

Attenzione: sort() e reverse() modificano l'originale e restituiscono None.

# ERRORE COMUNE
ordinata = lista.sort()   # ordinata = None!
# CORRETTO
lista.sort()
ordinata = sorted(lista)  # sorted() restituisce NUOVA lista

Lista vs Stringa (entrambe sequenze)

s = "Python"
l = list(s)        # ['P', 'y', 't', 'h', 'o', 'n']
"".join(l)         # "Python" (ricostruisce stringa)
"-".join(l)        # "P-y-t-h-o-n"

2. Dizionari: mapping chiave → valore

Creazione di un dizionario

vuoto = {}
giocatore = {
    "nome": "Alex",
    "livello": 5,
    "classe": "Mago",
    "punti_vita": 42,
    "inventario": ["pozione", "bacchetta"]
}
da_coppie = dict(nome="Sam", eta=12)  # {'nome': 'Sam', 'eta': 12}

Accesso e modifica

print(giocatore["nome"])        # Alex (KeyError se chiave manca)
print(giocatore.get("mana"))    # None (nessun errore)
print(giocatore.get("mana", 0)) # 0 (default se manca)

giocatore["livello"] = 6        # Modifica
giocatore["mana"] = 100         # Aggiunge nuova chiave
del giocatore["classe"]         # Rimuove chiave

Metodi principali

| Metodo | Esempio | Descrizione | | -------- | --------- | ------------- | | keys() | d.keys() | Vista chiavi (iterabile) | | values() | d.values() | Vista valori | | items() | d.items() | Vista coppie (chiave, valore) | | get(k, default) | d.get("x", 0) | Sicuro, con default | | setdefault(k, v) | d.setdefault("x", []) | Se manca, imposta e restituisce | | pop(k, default) | d.pop("x") | Rimuove e restituisce valore | | update(altro) | d1.update(d2) | Unisce (sovrascrive) | | copy() | d.copy() | Copia superficiale |

Iterazione

for chiave in giocatore:
    print(chiave, giocatore[chiave])

for chiave, valore in giocatore.items():
    print(f"{chiave}: {valore}")

# Solo valori
for v in giocatore.values():
    print(v)

3. Nesting: strutture complesse

Lista di dizionari (es. inventario oggetti)

inventario = [
    {"nome": "Spada", "tipo": "arma", "danno": 10, "quantita": 1},
    {"nome": "Pozione", "tipo": "consumabile", "effetto": "cura", "quantita": 5},
    {"nome": "Scudo", "tipo": "armatura", "difesa": 5, "quantita": 1},
]

# Cerca arma
for oggetto in inventario:
    if oggetto["tipo"] == "arma":
        print(f"Arma equipaggiata: {oggetto['nome']} ({oggetto['danno']} dmg)")

Dizionario di liste (es. drop table per mostro)

drop_table = {
    "Goblin": ["moneta", "pugnale", "straccio"],
    "Drago": ["scaglia_drago", "oro", "spada_leggendaria"],
    "Slime": ["gelatina", "gelatina", "pozione"],
}

mostro = "Drago"
print(f"Possibili drop da {mostro}: {drop_table[mostro]}")

Dizionario di dizionari (es. database giocatori)

database = {
    "alex123": {"eta": 13, "punteggio": 1500, "vip": True},
    "luna_gamer": {"eta": 12, "punteggio": 2100, "vip": False},
}

# Aggiorna punteggio
def aggiorna_punteggio(db, username, punti):
    if username in db:
        db[username]["punteggio"] += punti
    else:
        print("Utente non trovato")

aggiorna_punteggio(database, "alex123", 100)

4. Loop su collezioni: pattern comuni

Filtrare (list comprehension - anticipazione)

numeri = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pari = [n for n in numeri if n % 2 == 0]  # [2, 4, 6, 8, 10]
quadrati = [n**2 for n in numeri]         # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Con indice: enumerate()

armi = ["Spada", "Arco", "Bastone"]
for i, arma in enumerate(armi, start=1):
    print(f"{i}. {arma}")
# 1. Spada
# 2. Arco
# 3. Bastone

Più liste insieme: zip()

nomi = ["Guerriero", "Mago", "Ladro"]
vite = [100, 60, 80]
mana = [0, 100, 20]

for n, v, m in zip(nomi, vite, mana):
    print(f"{n}: HP={v} MP={m}")

5. Copia: superficiale vs profonda

import copy

originale = [[1, 2], [3, 4]]

superficiale = originale.copy()        # o list(originale) / originale[:]
profonda = copy.deepcopy(originale)

originale[0].append(99)

print(originale)    # [[1, 2, 99], [3, 4]]
print(superficiale) # [[1, 2, 99], [3, 4]]  ← CONDIVIDE liste interne!
print(profonda)     # [[1, 2], [3, 4]]       ← Indipendente

Regola: Se la lista/dizionario contiene altre liste/dizionari → usa copy.deepcopy().


6. Script completo: Sistema Inventario RPG

# inventario_rpg.py
"""Sistema inventario: aggiungi, rimuovi, usa, mostra, cerca."""

INVENTARIO_MAX = 20

class Inventario:
    def __init__(self):
        self.slot = []  # Lista di dict: {"nome": str, "tipo": str, "qta": int}
    
    def aggiungi(self, nome: str, tipo: str, qta: int = 1) -> bool:
        # Cerca se già presente (stackable)
        for item in self.slot:
            if item["nome"] == nome and item["tipo"] == tipo:
                item["qta"] += qta
                print(f"📦 {nome} x{qta} aggiunto (totale: {item['qta']})")
                return True
        # Nuovo slot
        if len(self.slot) >= INVENTARIO_MAX:
            print("❌ Inventario pieno!")
            return False
        self.slot.append({"nome": nome, "tipo": tipo, "qta": qta})
        print(f"✨ Nuovo oggetto: {nome} x{qta}")
        return True
    
    def rimuovi(self, nome: str, qta: int = 1) -> bool:
        for item in self.slot:
            if item["nome"] == nome:
                if item["qta"] <= qta:
                    self.slot.remove(item)
                    print(f"🗑️ {nome} rimosso completamente")
                else:
                    item["qta"] -= qta
                    print(f"🗑️ {nome} -{qta} (rimasti: {item['qta']})")
                return True
        print(f"❌ {nome} non trovato")
        return False
    
    def usa(self, nome: str) -> bool:
        for item in self.slot:
            if item["nome"] == nome:
                if item["tipo"] == "consumabile":
                    print(f"💊 Usi {nome}! Effetto applicato.")
                    return self.rimuovi(nome, 1)
                else:
                    print(f"❌ {nome} non è consumabile")
                    return False
        print(f"❌ {nome} non in inventario")
        return False
    
    def mostra(self):
        print("\n=== INVENTARIO ===")
        if not self.slot:
            print("  (vuoto)")
        else:
            for i, item in enumerate(self.slot, 1):
                print(f"  {i}. {item['nome']} ({item['tipo']}) x{item['qta']}")
        print(f"  Slot: {len(self.slot)}/{INVENTARIO_MAX}")
    
    def cerca_tipo(self, tipo: str) -> list:
        return [item for item in self.slot if item["tipo"] == tipo]


# Demo
if __name__ == "__main__":
    inv = Inventario()
    
    inv.aggiungi("Spada ferro", "arma", 1)
    inv.aggiungi("Pozione cura", "consumabile", 3)
    inv.aggiungi("Pozione cura", "consumabile", 2)  # Stack
    inv.aggiungi("Scudo legno", "armatura", 1)
    inv.mostra()
    
    inv.usa("Pozione cura")
    inv.mostra()
    
    print("\nArmi:", inv.cerca_tipo("arma"))
    print("Consumabili:", inv.cerca_tipo("consumabile"))

7. Tabella riassuntiva: quando usare lista vs dizionario

| Situazione | Struttura | Motivo | | ------------ | ----------- | -------- | | Sequenza ordinata (passi, livelli, log) | list | Indice ha significato | | Accesso per posizione (primo, ultimo, 5°) | list | lst[0], lst[-1] | | Mapping chiave→valore (config, stats, DB) | dict | d["chiave"] O(1) | | Chiavi uniche, lookup veloce | dict | Hash table | | Devi mantenere ordine inserimento | list o dict (Py 3.7+) | dict ora ordinato | | Contare occorrenze | dict o Counter | d[x] = d.get(x,0)+1 | | Pila (LIFO) / Coda (FIFO) | list / collections.deque | append/pop / popleft |


8. Esercizi pratici

  1. High-score: Lista di dizionari {"nome": "", "punteggio": 0}. Funzioni: aggiungi_punteggio(), top_10(), salva_carica() (JSON - anticipazione)
  2. Inventario completo: Estendi la classe sopra con: equipaggia, vendi, ordina per tipo/valore
  3. Rubrica: Dizionario nome -> {"telefono": "", "email": "", "compleanno": ""}. CRUD completo
  4. Mappa 2D: Lista di liste [[0,1,0],[1,1,1],[0,0,0]] (0=vuoto, 1=muro). Funzioni: stampa_mappa(), muovi_giocatore()
  5. Analisi testo: Conta frequenza parole in una frase → dizionario parola -> conteggio

9. Checklist fine capitolo

  • [ ] Crea liste e dizionari, accedi con [] e .get()
  • [ ] Usi slicing lst[start:stop:step] e indici negativi
  • [ ] Conosci metodi mutatori: append, pop, remove, sort, extend
  • [ ] Iteri con for x in lst, for k, v in d.items(), enumerate(), zip()
  • [ ] Gestisci nesting: lista di dict, dict di liste, dict di dict
  • [ ] Capisci copia superficiale vs deepcopy()

Prossimo capitolo

Capitolo 6: Moduli e librerie standard — import, random, time, math: usa il codice degli altri. Creare propri moduli, __name__ == "__main__", librerie esterne con pip.

👉 Leggi il Capitolo 6 →


Serie "Divento Programmatore: Python e i Giochi" (Cervello Elettronico Vol.2). Codice completo, tabelle, esercizi. Target 10-14 anni + guide adulti.

Per approfondire

Fonti e riferimenti

Condividi LinkedIn Facebook X WhatsApp
Continua a leggere

Tutti gli articoli del blog

Strumenti gratuiti