Coding for KidsCoding for Kids
Kreative NiveauerUdfordringerLærervejledning
Stem på funktioner
Avanceret Python Udviklingskursus
Kapitel
>
Niveau

Serialiseringsmoduler
Strukturmodul

Mål

Opsæt den endelige dataopdeling for den nye gård ved hjælp af struct-modulet.

For enden af vejen er der en tankstation, der administrerer den nye gård, som allerede er bygget, og de afgrøder, der allerede er plantet. Her vil vi inspicere og bearbejde dataene for de allerede plantede afgrøder og den forventede udbytte fra gården. Ligesom med de andre niveauer i dette kapitel, vil vi arbejde med serialisering og deserialisering af data, og introducere et sidste modul kaldet struct-modulet.

Struct-modulet introducerer en række serieliseringsfunktioner, der pakker data i binært format. I modsætning til de andre moduler, vi har arbejdet med, har du større kontrol over, hvordan vi kan strukturere dataene både når de er serieliseret og senere deserialiseret, hvilket gør det mere alsidigt end andre moduler. Brug import struct for at få adgang til følgende funktioner, som vi vil bruge til at bearbejde dataene:

  • struct.calcsize(): Bestemmer, hvor mange bytes der er pakket for en given formatstreng, den tager ét (1) argument, nemlig det format du ønsker at bekræfte byte-størrelsen for. De formater, vi vil bruge, er:
    • integer: repræsenteret som 'i' er formatet for data repræsenteret som hele tal
    • float: repræsenteret som 'f' er formatet for data repræsenteret som decimaltal
    • double: repræsenteret som 'd' er formatet for data repræsenteret som mere komplekse decimaltal, hvor float-formatet er utilstrækkeligt.
  • struct.pack(): Serieliserer data i binært format, pakket i et format efter eget valg. Du kan tage to (2) eller flere argumenter, hvor det første er det format, du ønsker at bruge, og derefter de værdier, du ønsker at serialisere. Formaterne er de tidligere beskrevne, og du skal tilføje dem i overensstemmelse med antallet af argumenter, du tilføjer.
  • struct.unpack(): Deserialiserer pakket binært data, tager to (2) argumenter, det format som dataene skal sammenlignes med, og det data, der blev serieliseret.
  • struct.iter_unpack(): Deserialiserer pakket binært data, fungerer på samme måde som struct.unpack() men itererer gennem hver datapakke individuelt ved hjælp af en løkke.
  • struct.pack_into(): En avanceret version af struct.pack(), der tager fire (4) argumenter: det format, du ønsker at bruge, databufferen hvor dataene skal indsættes, positionen i bufferen hvor dataene skal placeres, og til sidst den data du pakker.
  • struct.unpack_from(): En avanceret version af struct.unpack(), der tager tre (3) argumenter: det format, du ønsker at bruge, databufferen du ønsker at deserialisere fra, og til sidst den position i bufferen, du ønsker at deserialisere fra. Dette gør det muligt at udpakke specifikke dele af dataene.

Gå til den lyse X-mærke ved tankstationen og vend dig mod skranken, og opret tre (3) variabler med navn: integer, float og double. Vi vil bruge disse til at bekræfte størrelsen i bytes af hvert format ved brug af funktionen struct.calcsize(). For variablen integer skal du bruge funktionen med 'i' som argument, for variablen float skal du bruge funktionen med 'f' som argument, og til sidst for variablen double skal du bruge funktionen med 'd' som argument. For eksempel: integer = struct.calcsize('i'). Tilføj de tre (3) variabler til den forudskrevne write()-funktion.

Gå til det gyldne X-mærke og brug funktionen read() for at indsamle data om den nye gård. Notér datapunkterne og formatet til fremtidig brug, nemlig: Resources, Size og Estimate. Når du har noteret disse, skal du gå til det lyse X-mærke over den blå løber og oprette en variabel med navnet blue_data.

Med variablen blue_data skal du gemme resultatet af funktionen struct.pack(), og sætte som argumenter det format og de værdier, du tidligere noterede. Når du skriver formatet, skal du "pakke" formattyperne ind i en enkelt enhed. For eksempel, hvis integer-formatet er betegnet som 'i' som tidligere beskrevet, og du tilføjer tre heltal, skriver du det som 'iii'. Tilsvarende, hvis du tilføjer et heltal, et decimaltal og et double, skrives det som 'ifd'. Når du tilføjer dataene, placeres de individuelt som argumenter. Her er et overordnet eksempel:

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)

Funktionen struct.pack() giver stor fleksibilitet, da den gør det muligt at bestemme, hvordan du ønsker at formatere dataene og serielisere flere datapunkter på én gang, alt efter din præference. Tilføj de tidligere indsamlede data med udgangspunkt i eksemplet ovenfor. Brug funktionen display() med blue_data som argument for at se de pakkede data.

Gå til det mørke X-mærke over den blå løber og vend dig mod terminalen. Opret en variabel med navnet blue_unpack og gem resultatet af funktionen struct.unpack(), hvor du tilføjer det samme format, som du brugte til at pakke dataene, samt variablen blue_data som argumenter. Formatet skrives på samme måde som med funktionen struct.pack(), således at du kan deserialisere dataene på samme måde, som du oprindeligt serieliserede dem. Brug funktionen write() med blue_unpack som argument for at bekræfte de data, du tidligere pakkede.

På samme sted vil vi også bruge funktionen struct.iter_unpack(). Den tager præcis de samme argumenter som struct.unpack(), men nu er den formateret som en for-løkke, hvilket gør det muligt for os at iterere gennem dataene i stedet for blot at skrive dem alle ud. Funktionen er kodet således:

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

Vi vil bruge funktionen speak() til at vise værdierne. For de manglende argumenter i funktionen struct.iter_unpack(), tilføj de samme, som tidligere brugt med struct.unpack(), da disse er variationer af den samme funktion med hensyn til brug.

Gå til det gyldne X-mærke over den røde løber og vend dig mod skranken. Brug funktionen read() til at gennemgå afgrødemængderne. Notér alle mængderne og formatet for hver afgrøde. Gå derefter til det lyse X-mærke over den røde løber og opret et objekt med navnet buffer, og tildel det værdien bytearray(16). Dette er en samling af bytes, som vi kan adressere, inden vi fylder den, og til vores formål fungerer den som en databank, hvor du manuelt kan gemme dataene. Tallet 16 som argument repræsenterer, hvor mange bytes du kan gemme i objektet buffer.

Brug funktionen struct.pack_into() for at fylde den oprettede buffer med data. Det er ikke nødvendigt at oprette en variabel til at gemme resultatet af funktionen, da den selv indsætter værdierne direkte i buffer-objektet. Vi vil bruge funktionen for hver af de værdier, vi tidligere noterede, og udfylde deres argumenter tilsvarende.

For eksempel, for den første afgrødeværdi, vil du blive oplyst dens format, dens byteposition og dens mængde. Tilføj formatet som det første argument, placeringen hvor du ønsker at serialisere bytes til, som i dette tilfælde er buffer. For det tredje argument angives den position, hvor du ønsker at tilføje værdien i buffer; formatet bestemmer de bytes, der anvendes, så vær omhyggelig med at pakke data, der ikke allerede er optaget. Til sidst tilføjes den værdi, du ønsker at serialisere og pakke ind i buffer-objektet.

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

buffer-objektet har 16 bytes som tidligere angivet. I den ovenstående kode har integer-formatet 4 bytes og indsættes ved positionen 0. Dette betyder, at når dataene er indsat i buffer, er der kun 12 bytes tilbage i buffer, der er ledige, idet positionerne 0-3 er optaget af den angivne værdi, i dette tilfælde 82. Gør dette for alle de afgrødedatapunkter, der tidligere blev indsamlet og noteret, hvilket giver i alt tre (3). Brug funktionen display() og tilføj buffer for at vise de serialiserede data.

Gå til det mørke X-mærke over den røde løber og vend dig mod terminalen. Her vil vi deserialisere dataene for at bekræfte indholdet og sikre korrekt lagring. Opret tre variabler med navn: lettuce, carrots og melons. Vi vil pakke dataene for hvert datapunkt ud individuelt. For hver af variablerne skal du gemme resultatet af struct.unpack_from() og angive de samme data, som du noterede, da du pakkede dataene. For det første argument angives formatet, for det andet tilføjes buffer-objektet, og til sidst angives positionen i buffer, hvorfra du ønsker at pakke ud. For eksempel:

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

Disse data svarer til det tidligere pakkningseksempel, der nu bliver pakket ud. Gør det samme for de to andre variabler, og indsæt lettuce, carrots og melons i den forudskrevne write()-funktion for at fuldføre niveauet.

Kodebog