Coding for KidsCoding for Kids
Kreatív SzintekKihívásokTanári Útmutató
Szavazzon a funkciókra
Fejlett Python fejlesztési tanfolyam
Fejezet
>
Szint

Szerializációs modulok
Struktúra modul

Cél

Állítsd be az új mező végső adatbontását a struct modul segítségével.

Az út végén található egy benzinkút, amely az épített és már ültetett új mezőt kezeli. Itt megvizsgáljuk és feldolgozzuk az ültetett növények adatait, valamint a mező előrejelzett hozamát. Ahogy a fejezet többi szintjén, itt is az adatok szerializálásával és deszerializálásával foglalkozunk, bemutatva az utolsó modult, a struct modult.

A struct modul egy sor szerializációs függvényt vezet be, amelyek bináris formátumban csomagolják az adatokat, ellentétben a korábban használt modulokkal, hiszen nagyobb kontrollt biztosít arra, hogyan struktúrálhatjuk az adatokat mind a szerializálás, mind későbbi deszerializálás során, ezáltal sokoldalúbbá téve azt. Használd az import struct utasítást az alábbi függvények eléréséhez, amelyeket az adatok feldolgozásához fogunk használni:

  • struct.calcsize(): Megállapítja, hogy egy adott formátum sztring hány bájtot foglal, egy (1) argumentumot várva, amely a formátum, aminek a bájméretét szeretnéd ellenőrizni. A használni kívánt formátumok a következők:
    • egész szám: az 'i' formátum az egész számok ábrázolására szolgál
    • lebegőpontos szám: az 'f' formátum a tizedes számok ábrázolására szolgál
    • dupla precizitású szám: a 'd' formátum az összetettebb tizedes számok ábrázolására szolgál, ahol a lebegőpontos formátum nem elegendő.
  • struct.pack(): Szerializálja az adatokat bináris formátumban, a választott formátumban csomagolva. Két (2) vagy több argumentumot fogad: az első a használni kívánt formátum, a továbbiak pedig azok az értékek, amelyeket szerializálni szeretnél. A formátumok a korábban ismertetettek, és ennek megfelelően kell őket megadnod az argumentumok számával összhangban.
  • struct.unpack(): Deszerializálja a csomagolt bináris adatokat, két (2) argumentumot vár: az első a formátum, amelynek meg kell egyeznie azzal, amilyen formátumban az adatokat szerializáltuk, a második pedig az a szerializált adat.
  • struct.iter_unpack(): Deszerializálja a csomagolt bináris adatokat, ugyanúgy működik, mint a struct.unpack(), de egy ciklus segítségével egyenként iterálja végig az adatblokkokat.
  • struct.pack_into(): A struct.pack() fejlettebb változata, négy (4) argumentumot vár: az első a használni kívánt formátum, a második az adatpuffer, amelybe az adatokat be szeretnéd helyezni, a harmadik a puffer azon pozíciója, ahol az adatnak el kell helyezkednie, végül a csomagolni kívánt adat.
  • struct.unpack_from(): A struct.unpack() fejlettebb változata, három (3) argumentumot vár: az első a használni kívánt formátum, a második az adatpuffer, amelyből ki szeretnéd csomagolni az adatokat, és végül a puffer azon pozíciója, ahonnan kicsomagolni kívánsz. Ez lehetővé teszi, hogy az adatok meghatározott részeit csomagold ki.

Sétálj a világos X jelzés felé a benzinkútnál, és nézz a pultra, majd hozz létre három (3) változót: integer, float és double. Ezeket az struct.calcsize() függvény segítségével fogjuk használni az egyes formátumok bájtméretének ellenőrzésére. Az integer változó esetében használd a függvényt 'i' argumentummal, a float változó esetében 'f' argumentummal, végül a double változó esetében 'd' argumentummal. Például: integer = struct.calcsize('i'). Add hozzá a három (3) változót az előre megírt write() függvényhez.

Sétálj az arany X jelzés felé, és használd a read() függvényt az új mező adatainak összegyűjtésére, jegyezd fel az adatpontokat és a formátumot a jövőbeni használatra, nevezetesen: Resources, Size és Estimate. Miután feljegyezted ezeket, sétálj a világos X jelzés felé a kék szőnyegen, és hozz létre egy blue_data nevű változót.

A blue_data változóban tárold a struct.pack() függvény értékét, ahol argumentumként add meg azt a formátumot és az értékeket, amelyeket korábban feljegyeztél. A formátum megadásakor a formátumtípusokat egy egységbe kell "csomagolnod". Például, az előzőleg ismertetett egész szám formátumot 'i' jelöli; ha három egész számot adsz hozzá, akkor azt 'iii'-ként kell megadnod. Hasonlóan, ha egy egész számot, egy lebegőpontos számot és egy dupla precizitású számot adsz hozzá, akkor azt 'ifd'-ként kell megírnod. Az adatokat egyenként kell argumentumként megadnod. Íme egy általános példa:

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)

A struct.pack() függvény nagy rugalmasságot biztosít, lehetővé téve, hogy beállítsd, hogyan szeretnéd formázni az adatokat, és lehetőséget ad arra, hogy egyszerre több adatpontot szerializálj, a te választásod szerint. A fenti példát alapul véve add hozzá a korábban beolvasott adatokat. Használd a display() függvényt a blue_data argumentummal a csomagolt adatok megtekintéséhez.

Sétálj a sötét X jelzés felé a kék szőnyegen, és nézz a terminálra, majd hozz létre egy blue_unpack nevű változót, amelyben tárolod a struct.unpack() függvény értékét, megadva ugyanazt a formátumot, amellyel az adatokat csomagoltad, valamint a blue_data változót argumentumként. A formátumot ugyanolyan módon írd, mint a struct.pack() esetében, így az adatokat ugyanolyan módon tudod deszerializálni, ahogyan szerializáltad őket. Használd a write() függvényt a blue_unpack argumentummal a korábban csomagolt adatok ellenőrzéséhez.

Ugyanezen a helyen használni fogjuk a struct.iter_unpack() függvényt is, amely pontosan ugyanazokat az argumentumokat veszi fel, mint a struct.unpack(), de most egy for ciklus formájában van megadva, így az adatokat iterálhatjuk, ahelyett, hogy egyszerűen kiírnánk őket. A függvény a következő módon van kódolva:

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

A speak() függvényt fogjuk használni az értékek megjelenítéséhez; a struct.iter_unpack() függvény hiányzó argumentumaihoz add hozzá ugyanazokat, amelyeket korábban a struct.unpack() esetében használtál, hiszen ezek a függvények ugyanannak a funkciónak a variációi használat szempontjából.

Sétálj az arany X jelzés felé a piros szőnyegen, és nézz a pultra, majd használd a read() függvényt a növénymennyiségek áttekintéséhez. Jegyezd fel az összes mennyiséget és az egyes növények formátumát. Ezután sétálj a világos X jelzés felé a piros szőnyegen, és hozz létre egy buffer nevű objektumot, amelyhez rendeld hozzá a bytearray(16) értéket. Ez egy bájt-gyűjtemény, amelyet előzetesen címkézhetünk, mielőtt feltöltenénk, számunkra úgy működik, mint egy adatbank, ahol manuálisan tárolhatod az adatokat. A 16 argumentum azt jelzi, hogy hány bájtot tudsz eltárolni a buffer objektumban.

Használd a struct.pack_into() függvényt a létrehozott buffer objektum feltöltéséhez. Nem szükséges változót létrehozni a függvény értékének tárolására, mivel a függvény közvetlenül behelyezi az adatokat a buffer objektumba. Ezt a függvényt fogjuk használni minden korábban feljegyzett értékhez, az argumentumok megfelelő kitöltésével.

Például, az első megadott növényérték esetében megkapod a formátumot, a bájt pozíciót és a mennyiséget. Az első argumentumban add meg a formátumot, a másodikban azt a helyet, ahova a bájtokat szériálni szeretnéd (ebben az esetben a buffer-t). A harmadik argumentumban add meg a pozíciót a buffer-en belül, ahol az értéket el kívánod helyezni; a formátum határozza meg az elfoglalt bájtokat, így ügyelj arra, hogy ne pakolj olyan adatot, ami már foglalt. Végül add hozzá azt az értéket, amelyet szerializálni és bekeretezni kívánsz a buffer objektumba.

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

Ahogy korábban említettük, a buffer objektumnak 16 bájtja van; a fenti kódban az egész szám formátum 4 bájtot használ, és a 0 pozícióban kerül behelyezésre. Ez azt jelenti, hogy miután az adat bekerült a buffer-be, csak 12 bájt marad szabadon, hiszen a 0-3 pozíciókat az adott érték (jelen esetben 82) foglalja el. Ezt végezd el az összes, korábban felolvasott és feljegyzett növény adatponttal (összesen 3 db). Használd a display() függvényt, és add meg a buffer-t a szerializált adatok megjelenítéséhez.

Sétálj a sötét X jelzés felé a piros szőnyegen, és nézz a terminálra, itt fogjuk deszerializálni az adatokat a tartalom ellenőrzése végett, hogy biztosítsuk a helyes tárolást. Hozz létre három változót: lettuce, carrots és melons, és egyenként csomagold ki az egyes adatpontokat. Mindegyik változóban tárold a struct.unpack_from() függvény értékét, és add meg argumentumként ugyanazokat az adatokat, amelyeket a csomagoláskor használtál. Az első argumentumként add meg a formátumot, a másodikban add hozzá a buffer objektumot, ahonnan ki szeretnéd csomagolni az adatokat, és végül add meg azt a pozíciót a buffer-ben, ahonnan a kicsomagolást szeretnéd kezdeni. Például:

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

Ez az adat megfelel az előző csomagolási példa deszerializálásának, végezd ugyanezt a két másik változóval, és illeszd be a lettuce, carrots és melons változókat az előre megírt write() függvénybe a szint befejezéséhez.

Kódkönyv