Coding for KidsCoding for Kids
Livelli CreativiSfideGuida per Insegnanti
Vota per le funzionalità
Corso Avanzato di Sviluppo Python
Capitolo
>
Livello

Moduli di serializzazione
Modulo Struct

Obiettivo

Imposta la suddivisione finale dei dati per la nuova azienda agricola utilizzando il modulo struct.

Alla fine della strada c'è una stazione di servizio che amministra la nuova azienda agricola già costruita e i campi già piantati. Qui ispezioneremo ed elaboreremo i dati relativi alle colture già piantate e alla resa prevista dell'azienda agricola. Come per gli altri livelli di questo capitolo, lavoreremo con la serializzazione e la deserializzazione dei dati, introducendo un ultimo modulo chiamato struct module.

Il modulo struct introduce una serie di funzioni di serializzazione che confezionano i dati in formato binario. A differenza degli altri moduli con cui abbiamo lavorato, tuttavia, offre un maggiore controllo su come strutturare i dati sia durante la serializzazione che nella successiva deserializzazione, rendendolo più versatile rispetto agli altri moduli. Utilizza import struct per accedere alle seguenti funzioni che useremo per elaborare i dati:

  • struct.calcsize(): Determina quanti byte vengono utilizzati per confezionare una data stringa di formato; prende un argomento, ovvero il formato di cui vuoi verificarne la dimensione in byte. I formati che useremo sono:
    • integer: rappresentato da 'i' ed è il formato per i dati rappresentati da numeri interi
    • float: rappresentato da 'f' ed è il formato per i dati rappresentati da numeri decimali
    • double: rappresentato da 'd' ed è il formato per i dati rappresentati da numeri decimali più complessi, dove il formato float non è sufficiente.
  • struct.pack(): Serializza i dati in formato binario, confezionandoli in un formato a tua scelta. Può prendere due o più argomenti, ovvero il formato che desideri utilizzare e i valori che vuoi serializzare. I formati sono quelli precedentemente indicati e dovrai aggiungerli in corrispondenza della quantità di valori forniti.
  • struct.unpack(): Deserializza i dati binari confezionati; prende due argomenti, il formato che deve essere conforme a quello in cui i dati sono stati serializzati e, come secondo argomento, i dati serializzati.
  • struct.iter_unpack(): Deserializza i dati binari confezionati; funziona allo stesso modo di struct.unpack() ma itera su ogni blocco di dati individualmente grazie all'uso di un ciclo.
  • struct.pack_into(): Una versione avanzata di struct.pack(), prende quattro argomenti: il formato che vuoi utilizzare, il buffer di dati in cui inserire i dati, la posizione nel buffer che desideri occupare e infine i dati da confezionare.
  • struct.unpack_from(): Una versione avanzata di struct.unpack(), prende tre argomenti: il formato che vuoi utilizzare, il buffer di dati da cui deserializzare e infine la posizione nel buffer dalla quale deserializzare. Questo ti permette di deserializzare specifiche porzioni dei dati.

Cammina verso la X segnata di luce nella stazione di servizio e rivolgi lo sguardo al bancone: crea tre variabili denominate integer, float e double. Le useremo per verificare la dimensione in byte di ciascun formato utilizzando la funzione struct.calcsize(). Per la variabile integer usa la funzione con 'i' come argomento, per la variabile float usa la funzione con 'f' come argomento e, infine, per la variabile double usa la funzione con 'd' come argomento. Ad esempio: integer = struct.calcsize('i'). Aggiungi le tre variabili alla funzione write() pre-scritta.

Cammina verso la X segnata in oro e utilizza la funzione read() per raccogliere i dati relativi alla nuova azienda agricola; prendi nota dei punti dati e del formato per uso futuro, nello specifico: Resources, Size e Estimate. Una volta presa nota, cammina verso la X segnata di luce sul tappeto blu e crea una variabile chiamata blue_data.

Nella variabile blue_data memorizza il valore della funzione struct.pack(), impostando come argomenti il formato e i valori di cui hai preso nota in precedenza. Quando scrivi il formato, devi "confezionare" i tipi di formato in un'unica unità. Ad esempio, il formato per un intero è indicato come 'i' come descritto in precedenza; se stai aggiungendo tre numeri interi, li specifichi come 'iii'. Allo stesso modo, se stai aggiungendo un intero, un float e un double, sarà scritto 'ifd'. Quando aggiungi i dati, li inserisci individualmente come argomenti. Ecco un esempio complessivo:

data_1 = 8 # is an integer data_2 = 2.25 # is a float data_3 = 900.702938103 # is a double blue_data = struct.pack('ifd', data_1, data_2, data_3)

La funzione struct.pack() offre molta flessibilità, permettendoti di stabilire come formattare i dati e di serializzare simultaneamente più punti dati a tuo piacimento. Aggiungi i dati precedentemente letti utilizzando l'esempio sopra come base. Usa la funzione display() con blue_data come argomento per visualizzare i dati confezionati.

Cammina verso la X segnata di luce scura sul tappeto blu e rivolgi lo sguardo al terminale: crea una variabile chiamata blue_unpack e memorizza il valore della funzione struct.unpack(), utilizzando lo stesso formato impiegato per confezionare i dati e la variabile blue_data come argomenti. Il formato è scritto nello stesso modo della funzione struct.pack(), in modo da poter deserializzare i dati nello stesso modo in cui sono stati serializzati. Utilizza la funzione write() con blue_unpack come argomento per verificare i dati che hai confezionato in precedenza.

Nella stessa posizione utilizzeremo anche la funzione struct.iter_unpack(). Essa accetta esattamente gli stessi argomenti di struct.unpack(), ma viene utilizzata all'interno di un ciclo for, il che ci permette di iterare sui dati anziché visualizzarli tutti in una volta. La funzione è codificata come segue:

for values in struct.iter_unpack(-insert value-, -insert value-): player.speak(values)

Utilizzeremo la funzione speak() per visualizzare i valori; per gli argomenti mancanti nella funzione struct.iter_unpack(), aggiungi gli stessi utilizzati in precedenza con struct.unpack(), poiché si tratta di varianti della stessa funzione, in termini di utilizzo.

Cammina verso la X segnata in oro sul tappeto rosso e rivolgi lo sguardo al bancone: utilizza la funzione read() per esaminare le quantità delle colture. Prendi nota di tutte le quantità e del formato per ciascuna coltura. Cammina verso la X segnata di luce sul tappeto rosso e crea un oggetto chiamato buffer, assegnandogli il valore di bytearray(16). Si tratta di una raccolta di byte a cui possiamo accedere prima di popolarla; per i nostri scopi funziona come una banca dati dove puoi memorizzare i dati manualmente. Il numero 16 come argomento rappresenta la lunghezza, ovvero quanti byte puoi memorizzare nell'oggetto buffer.

Utilizza la funzione struct.pack_into() per popolare l'oggetto buffer che hai creato. Non è necessario creare una variabile per memorizzare il valore della funzione, poiché la funzione stessa inserir�e0 i valori direttamente nell'oggetto buffer. Utilizzerai la funzione per ciascuno dei valori di coltura che hai notato, inserendo i relativi argomenti.

Ad esempio, per il primo valore della coltura fornito, ti verranno indicati il formato, la posizione in byte e la quantità. Aggiungi il formato come primo argomento, la destinazione in cui desideri serializzare i byte (in questo caso buffer) e, come terzo argomento, la posizione all'interno del buffer in cui inserire il valore, tenendo presente che il formato determina i byte occupati, in modo da confezionare dati in spazi non precedentemente utilizzati. Infine, aggiungi il valore che desideri serializzare e inserire nell'oggetto buffer.

struct.pack_into('i', buffer, 0, 82)

L'oggetto buffer ha 16 byte, come indicato in precedenza; nel codice fornito sopra, il formato per un intero occupa 4 byte ed �e8 inserito in posizione 0. Ci�f2 significa che, una volta inseriti i dati nel buffer, rimangono solo 12 byte liberi, dato che le posizioni da 0 a 3 sono occupate dal valore fornito, in questo caso 82. Esegui l'operazione per tutti i punti dati relativi alle colture notati in precedenza; in totale sono tre (3). Utilizza la funzione display() e passa buffer come argomento per visualizzare i dati serializzati.

Cammina verso la X segnata di luce scura sul tappeto rosso e rivolgi lo sguardo al terminale: qui deserializzeremo i dati per verificarne il contenuto, al fine di assicurarci che siano stati memorizzati correttamente. Crea tre variabili denominate lettuce, carrots e melons; deserializzeremo i dati relativi a ciascun punto in modo individuale. Per ciascuna variabile, memorizza il valore di struct.unpack_from() e imposta come argomenti gli stessi dati che hai utilizzato per confezionare i dati. Per il primo argomento specifica il formato, per il secondo fornisci l'oggetto buffer da cui deserializzare e, infine, per il terzo argomento indica la posizione nel buffer da cui desideri deserializzare. Ad esempio:

lettuce = struct.unpack_from('i', buffer, 0)

Questi dati corrispondono all'esempio di packing precedente, che ora viene deserializzato; procedi allo stesso modo per le altre due variabili e inserisci lettuce, carrots e melons nella funzione write() pre-scritta per completare il livello.

Libro del Codice