Python e dizionari: gestire un catalogo di prodotti con varianti e attributi

by theArchitect
SHARE
Python e dizionari: gestire un catalogo di prodotti con varianti e attributi
© Guida-HTML5.it

Introduzione

I dizionari sono una delle strutture dati più utili di Python quando devi rappresentare informazioni associative, cioè dati composti da chiavi e valori. Un caso molto pratico è la gestione di un catalogo di prodotti, dove ogni prodotto può avere attributi diversi: nome, prezzo, categoria, disponibilità, varianti di colore o taglia, e così via.

Questo tutorial ti mostra come usare i dizionari per costruire un piccolo sistema di catalogo flessibile, adatto a progetti reali come e-commerce, gestionali, app interne o prototipi API. L’obiettivo non è solo memorizzare dati, ma anche organizzarli bene, aggiornarli in modo sicuro e interrogarli facilmente.

Il sotto-argomento scelto è utile perché spesso i prodotti non sono tutti uguali: alcuni hanno varianti, altri no; alcuni hanno sconti, altri hanno attributi extra. I dizionari permettono di modellare questa variabilità in modo naturale.

Codice completo

from pprint import pprint

# Catalogo prodotti:
# La chiave esterna è il codice prodotto (SKU)
# Il valore è un dizionario con i dati del prodotto
catalogo = {
    "TSHIRT-001": {
        "nome": "T-shirt basic",
        "categoria": "abbigliamento",
        "prezzo": 14.90,
        "disponibile": True,
        "attributi": {
            "taglie": ["S", "M", "L", "XL"],
            "colori": ["bianco", "nero", "blu"]
        }
    },
    "MUG-010": {
        "nome": "Tazza personalizzata",
        "categoria": "home",
        "prezzo": 9.50,
        "disponibile": True,
        "attributi": {
            "materiale": "ceramica",
            "capacita_ml": 350
        }
    },
    "NOTE-200": {
        "nome": "Quaderno A5",
        "categoria": "ufficio",
        "prezzo": 4.20,
        "disponibile": False,
        "attributi": {
            "pagine": 120,
            "copertina": "rigida"
        }
    }
}


def mostra_prodotto(sku):
    """Stampa i dettagli di un prodotto se esiste nel catalogo."""
    prodotto = catalogo.get(sku)

    if prodotto is None:
        print(f"Prodotto {sku} non trovato.")
        return

    print(f"SKU: {sku}")
    print(f"Nome: {prodotto[´nome´]}")
    print(f"Categoria: {prodotto[´categoria´]}")
    print(f"Prezzo: €{prodotto[´prezzo´]:.2f}")
    print(f"Disponibile: {´sì´ if prodotto[´disponibile´] else ´no´}")

    print("Attributi:")
    for chiave, valore in prodotto["attributi"].items():
        print(f"  - {chiave}: {valore}")


def aggiorna_prezzo(sku, nuovo_prezzo):
    """Aggiorna il prezzo di un prodotto esistente."""
    if sku in catalogo:
        catalogo[sku]["prezzo"] = nuovo_prezzo
        print(f"Prezzo di {sku} aggiornato a €{nuovo_prezzo:.2f}")
    else:
        print(f"Impossibile aggiornare: {sku} non esiste.")


def aggiungi_variante(sku, tipo_variante, valore):
    """Aggiunge una variante o un attributo al prodotto."""
    if sku not in catalogo:
        print(f"Prodotto {sku} non trovato.")
        return

    attributi = catalogo[sku].setdefault("attributi", {})
    attributi[tipo_variante] = valore
    print(f"Aggiunto attributo ´{tipo_variante}´ a {sku}.")


def prodotti_per_categoria(categoria):
    """Restituisce una lista di SKU appartenenti a una categoria."""
    risultati = []

    for sku, prodotto in catalogo.items():
        if prodotto["categoria"] == categoria:
            risultati.append(sku)

    return risultati


def prodotti_disponibili():
    """Restituisce i prodotti disponibili."""
    return {
        sku: dati
        for sku, dati in catalogo.items()
        if dati["disponibile"]
    }


# Esempi di utilizzo
print("=== DETTAGLIO PRODOTTO ===")
mostra_prodotto("TSHIRT-001")

print("n=== AGGIORNAMENTO PREZZO ===")
aggiorna_prezzo("MUG-010", 8.90)

print("n=== AGGIUNTA VARIANTE ===")
aggiungi_variante("TSHIRT-001", "fit", "regular")

print("n=== PRODOTTI IN CATEGORIA ´abbigliamento´ ===")
print(prodotti_per_categoria("abbigliamento"))

print("n=== PRODOTTI DISPONIBILI ===")
pprint(prodotti_disponibili())

Spiegazione

1. Struttura del catalogo

La variabile catalogo è un dizionario principale. Ogni chiave è uno SKU, cioè un codice univoco prodotto come TSHIRT-001. Il valore associato è un altro dizionario con i dettagli del prodotto.

Questa scelta è molto pratica perché ti consente di trovare un prodotto in modo immediato usando il suo codice. In un catalogo reale, lo SKU è spesso il riferimento più affidabile per identificare un articolo.

2. Dizionari annidati

All’interno di ogni prodotto troviamo un secondo dizionario chiamato attributi. Questo è un esempio di dizionario annidato. Serve quando i dati sono strutturati in più livelli.

Per esempio, una maglietta può avere taglie e colori, mentre una tazza può avere materiale e capacità. Non ha senso forzare tutti i prodotti ad avere gli stessi campi: i dizionari permettono di modellare questa differenza in modo naturale.

3. Accesso sicuro con get()

La funzione mostra_prodotto() usa catalogo.get(sku) invece di catalogo[sku]. È una scelta importante:

  • catalogo[sku] genera un errore se la chiave non esiste.
  • catalogo.get(sku) restituisce None se la chiave manca, permettendoti di gestire il caso in modo elegante.

Questo approccio è molto utile quando i dati arrivano da input esterni, file o API.

4. Aggiornamento dei valori

La funzione aggiorna_prezzo() mostra come modificare un valore dentro un dizionario annidato:

catalogo[sku]["prezzo"] = nuovo_prezzo

Qui stai accedendo prima al prodotto, poi al campo prezzo. È una delle operazioni più comuni con i dizionari: leggere, modificare, aggiungere o rimuovere campi.

5. Uso di setdefault()

La funzione aggiungi_variante() utilizza setdefault() per garantire che il dizionario attributi esista. Questo metodo è molto comodo quando non sei sicuro che una chiave sia già presente.

In pratica:

  • se attributi esiste, lo usa;
  • se non esiste, lo crea con un dizionario vuoto.

È una soluzione pulita per evitare controlli manuali troppo verbosi.

6. Ricerca per categoria

La funzione prodotti_per_categoria() scorre il catalogo con items() e raccoglie gli SKU dei prodotti appartenenti a una categoria specifica. È un esempio classico di filtro sui dati contenuti in un dizionario.

Se invece vuoi ottenere direttamente i prodotti disponibili, la funzione prodotti_disponibili() usa una dictionary comprehension, che è una forma compatta e leggibile per costruire un nuovo dizionario filtrato.

Best practice

  • Usa chiavi stabili e univoche: nello scenario dei cataloghi, lo SKU è perfetto perché identifica ogni prodotto in modo affidabile.
  • Evita dizionari troppo profondi: i dizionari annidati sono utili, ma se la struttura diventa eccessivamente complessa può essere meglio passare a classi o dataclass.
  • Preferisci get() quando i dati possono mancare: riduce il rischio di KeyError e migliora la robustezza del codice.
  • Usa setdefault() con criterio: è ottimo per inizializzare strutture opzionali, ma non abusarne se il flusso diventa poco chiaro.
  • Separa dati e logica: il dizionario deve contenere i dati, mentre le funzioni devono occuparsi delle operazioni sul catalogo.
  • Valida i valori in ingresso: prima di aggiornare un prezzo o aggiungere un attributo, controlla che il dato sia corretto.
  • Usa nomi coerenti: chiavi come prezzo, categoria, disponibile devono essere uniformi in tutto il progetto.

Riepilogo

I dizionari in Python non servono solo a cercare valori rapidamente: sono uno strumento flessibile per modellare dati reali. In questo tutorial hai visto come costruire un catalogo di prodotti con attributi variabili, come leggere e modificare i dati, come filtrare i prodotti e come gestire strutture annidate.

Il vantaggio principale è la flessibilità: puoi rappresentare oggetti diversi senza dover creare una struttura rigida per ogni caso. Questo rende i dizionari ideali per prototipi, script di automazione, backend leggeri e gestione di dati semi-strutturati.

Se vuoi fare un passo avanti, puoi estendere questo esempio con:

  • salvataggio del catalogo in JSON;
  • gestione di sconti e promozioni;
  • ricerca per intervallo di prezzo;
  • ordinamento dei prodotti per disponibilità o costo;
  • integrazione con file CSV o database.

Approfondisci con risorse ufficiali

  • Documentazione Python sui dizionari: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict
  • Funzioni built-in utili: https://docs.python.org/3/library/functions.html
  • PEP 584 - operatori di unione dei dizionari: https://peps.python.org/pep-0584/
  • PEP 468 - preservare l’ordine degli argomenti keyword: https://peps.python.org/pep-0468/

SHARE