Cicli for e while in Python per elaborare dati a blocchi e paginazione

by theArchitect
SHARE
Cicli for e while in Python per elaborare dati a blocchi e paginazione
© Guida-HTML5.it

Introduzione

Quando un programma deve elaborare molti dati, caricare tutto in memoria in una sola volta può diventare inefficiente o addirittura impossibile. Un approccio più solido consiste nel lavorare a blocchi, chiamati anche batch o pagine. In questo modo il programma legge una quantità limitata di elementi, li elabora, libera le risorse e passa al blocco successivo.

In questo tutorial vedremo come combinare i cicli for e while per simulare l’elaborazione paginata di ordini. Il ciclo while sarà utile per richiedere continuamente nuove pagine finché esistono dati disponibili, mentre il ciclo for elaborerà singolarmente gli elementi contenuti in ogni pagina.

Questo schema è comune in diversi contesti reali:

  • lettura di risultati restituiti da un’API;
  • elaborazione di record provenienti da un database;
  • importazione di prodotti o clienti a blocchi;
  • invio di notifiche senza sovraccaricare un servizio;
  • esecuzione di attività su grandi raccolte di dati.

Codice completo

# Dati disponibili, organizzati in pagine da cinque elementi.
ordini = [
    {"id": 101, "cliente": "Anna", "totale": 49.90},
    {"id": 102, "cliente": "Luca", "totale": 120.00},
    {"id": 103, "cliente": "Marta", "totale": 15.50},
    {"id": 104, "cliente": "Paolo", "totale": 89.99},
    {"id": 105, "cliente": "Giulia", "totale": 210.00},
    {"id": 106, "cliente": "Sara", "totale": 32.40},
    {"id": 107, "cliente": "Marco", "totale": 75.00},
    {"id": 108, "cliente": "Elena", "totale": 18.90},
    {"id": 109, "cliente": "Davide", "totale": 140.00},
    {"id": 110, "cliente": "Chiara", "totale": 63.20},
    {"id": 111, "cliente": "Fabio", "totale": 99.90},
]

dimensione_pagina = 4
indice_inizio = 0
totale_elaborato = 0
numero_pagina = 1

# Il while continua finché l´indice non supera la quantità di dati.
while indice_inizio < len(ordini):
    indice_fine = indice_inizio + dimensione_pagina

    # Otteniamo una porzione della lista.
    pagina_corrente = ordini[indice_inizio:indice_fine]

    print(f"nElaborazione pagina {numero_pagina}")

    # Il for analizza ogni ordine presente nella pagina.
    for ordine in pagina_corrente:
        if ordine["totale"] >= 100:
            categoria = "ordine di valore elevato"
        else:
            categoria = "ordine standard"

        print(
            f"Ordine #{ordine[´id´]} - "
            f"{ordine[´cliente´]}: "
            f"{ordine[´totale´]:.2f} euro ({categoria})"
        )

        totale_elaborato += ordine["totale"]

    # Avanziamo alla pagina successiva.
    indice_inizio = indice_fine
    numero_pagina += 1

print(f"nTotale complessivo elaborato: {totale_elaborato:.2f} euro")
print(f"Numero di pagine processate: {numero_pagina - 1}")

Spiegazione

Il ruolo del ciclo while

La condizione del ciclo è:

while indice_inizio < len(ordini):

indice_inizio rappresenta la posizione del primo elemento della pagina corrente. Finché questa posizione è inferiore alla lunghezza della lista, significa che ci sono ancora ordini da elaborare.

A ogni iterazione calcoliamo il limite finale della pagina:

indice_fine = indice_inizio + dimensione_pagina

Successivamente aggiorniamo l’indice:

indice_inizio = indice_fine

Questo aggiornamento è fondamentale. Se venisse dimenticato, la condizione del while rimarrebbe sempre vera e il programma entrerebbe in un ciclo infinito.

Il ruolo del ciclo for

Il ciclo for lavora sugli elementi della pagina appena estratta:

for ordine in pagina_corrente:

Non è necessario conoscere gli indici degli elementi. Python assegna direttamente ogni dizionario alla variabile ordine, rendendo il codice più leggibile.

All’interno del ciclo viene applicata una regola semplice: gli ordini con valore almeno pari a 100 euro vengono classificati come ordini di valore elevato. Il totale viene accumulato nella variabile totale_elaborato.

Le fette delle liste

L’istruzione:

pagina_corrente = ordini[indice_inizio:indice_fine]

crea una nuova lista contenente gli elementi compresi tra l’indice iniziale e quello finale. Se l’ultimo blocco contiene meno elementi della dimensione richiesta, Python lo gestisce automaticamente senza generare un errore. Per esempio, con 11 ordini e pagine da 4, le pagine conterranno rispettivamente 4, 4 e 3 elementi.

Adattare il codice a un’API

In un’applicazione reale, al posto della lista completa si potrebbe usare una funzione che restituisce una pagina alla volta:

def recupera_pagina(numero_pagina, dimensione):
    # In un progetto reale qui potrebbe esserci una richiesta HTTP.
    inizio = (numero_pagina - 1) * dimensione
    fine = inizio + dimensione
    return ordini[inizio:fine]

Il ciclo while potrebbe quindi richiamare questa funzione finché restituisce una lista vuota. Questo modello rispecchia il funzionamento di molte API paginated.

Best practice

  • Aggiornare sempre la variabile di controllo: in un ciclo while l’indice, il contatore o lo stato di avanzamento devono cambiare a ogni iterazione.
  • Scegliere una dimensione del blocco ragionevole: blocchi troppo piccoli aumentano il numero di operazioni; blocchi troppo grandi consumano più memoria.
  • Separare recupero ed elaborazione: una funzione può ottenere i dati, mentre un’altra può elaborarli. Il codice diventa più facile da testare.
  • Usare nomi descrittivi: variabili come indice_inizio, dimensione_pagina e pagina_corrente chiariscono l’algoritmo.
  • Gestire le pagine vuote: quando i dati provengono da un servizio esterno, una pagina vuota dovrebbe normalmente terminare il ciclo.
  • Limitare le responsabilità del ciclo: evitare di inserire nello stesso ciclo recupero dati, formattazione, salvataggio e gestione di molti casi diversi.
  • Considerare gli iteratori: per flussi molto grandi, generatori e iteratori possono ridurre ulteriormente il consumo di memoria.

Riepilogo

Il ciclo while è adatto a gestire un’elaborazione che continua finché esistono nuove pagine o blocchi di dati. Il ciclo for, invece, è ideale per visitare gli elementi contenuti nel blocco corrente.

La combinazione dei due cicli permette di progettare programmi più efficienti e scalabili. Il principio generale è semplice: recuperare un blocco, elaborarne ogni elemento, aggiornare la posizione e ripetere fino alla fine dei dati.

Questo schema può essere applicato a ordini, utenti, prodotti, eventi o qualsiasi altra collezione che debba essere gestita progressivamente, evitando di caricare e trattare tutto in una sola operazione.

Approfondisci con risorse ufficiali

SHARE