Προχωρημένο Μάθημα Ανάπτυξης Python
Κεφάλαιο
>
Επίπεδο

Μονάδες Σειριοποίησης
Μονάδα Δομών

Στόχος

Οργάνωσε τον τελικό διαχωρισμό δεδομένων για τη νέα αγροτική έκταση χρησιμοποιώντας το module struct.

Στο τέλος του δρόμου υπάρχει ένας σταθμός εξυπηρέτησης που διαχειρίζεται τη νέα αγροτική έκταση που έχει ήδη κατασκευαστεί και τις καλλιέργειες που έχουν ήδη φυτευθεί. Εδώ θα εξετάσουμε και θα επεξεργαστούμε τα δεδομένα των ήδη φυτεμένων καλλιεργειών και την προβλεπόμενη απόδοση της αγροτικής έκτασης. Όπως και στα άλλα επίπεδα αυτού του κεφαλαίου, θα δουλέψουμε με σειριοποίηση και αποσειριοποίηση δεδομένων, εισάγοντας ένα τελευταίο module με όνομα struct.

Το module struct εισάγει μια σειρά από συναρτήσεις σειριοποίησης που πακετάρουν δεδομένα σε δυαδική μορφή. Σε αντίθεση με τα άλλα modules με τα οποία έχουμε δουλέψει, εδώ έχετε μεγαλύτερο έλεγχο στο πώς δομούνται τα δεδομένα κατά τη σειριοποίηση και την αποσειριοποίηση, καθιστώντας το πιο ευέλικτο από τα άλλα modules. Χρησιμοποιήστε import struct για να αποκτήσετε πρόσβαση στις παρακάτω συναρτήσεις που θα χρησιμοποιήσουμε για τη διαχείριση των δεδομένων:

  • struct.calcsize(): Προσδιορίζει πόσα bytes κατανέμονται σε μια δεδομένη συμβολοσειρά μορφοποίησης. Δέχεται ένα (1) όρισμα, που είναι η μορφή της οποίας θέλετε να επαληθεύσετε το μέγεθος σε bytes. Οι μορφές που θα χρησιμοποιήσουμε είναι:
    • integer: αναπαρίσταται ως 'i' και είναι η μορφή για δεδομένα που εκφράζονται με ακέραιους αριθμούς
    • float: αναπαρίσταται ως 'f' και είναι η μορφή για δεδομένα με δεκαδικούς αριθμούς
    • double: αναπαρίσταται ως 'd' και είναι η μορφή για πιο σύνθετους δεκαδικούς αριθμούς, όταν η μορφή float δεν επαρκεί
  • struct.pack(): Σειριοποιεί δεδομένα σε δυαδική μορφή, πακεταρισμένα σύμφωνα με τη μορφή που επιλέγετε. Μπορεί να δεχθεί δύο (2) ή περισσότερα ορίσματα: το πρώτο είναι η μορφή που θέλετε να χρησιμοποιήσετε και τα υπόλοιπα είναι οι τιμές που θέλετε να σειριοποιήσετε. Οι μορφές είναι αυτές που περιγράφηκαν παραπάνω και πρέπει να τις προσθέσετε ανάλογα με τον αριθμό των ορισμάτων που δίνετε.
  • struct.unpack(): Αποσειριοποιεί πακεταρισμένα δυαδικά δεδομένα. Δέχεται δύο (2) ορίσματα: το πρώτο είναι η μορφή με την οποία έγινε η σειριοποίηση, και το δεύτερο είναι τα σειριοποιημένα δεδομένα.
  • struct.iter_unpack(): Αποσειριοποιεί πακεταρισμένα δυαδικά δεδομένα, λειτουργώντας με τον ίδιο τρόπο όπως η struct.unpack(), αλλά επαναλαμβάνει τη διαδικασία για κάθε μπλοκ δεδομένων ξεχωριστά μέσω ενός βρόχου.
  • struct.pack_into(): Μια προχωρημένη έκδοση της struct.pack(), δέχεται τέσσερα (4) ορίσματα: τη μορφή που θέλετε να χρησιμοποιήσετε, τον buffer δεδομένων στον οποίο θέλετε να εισαχθούν τα δεδομένα, τη θέση μέσα στον buffer όπου θα τοποθετηθούν, και τέλος τα δεδομένα που θα πακεταριστούν.
  • struct.unpack_from(): Μια προχωρημένη έκδοση της struct.unpack(), δέχεται τρία (3) ορίσματα: τη μορφή που θέλετε να χρησιμοποιήσετε, τον buffer δεδομένων από τον οποίο θέλετε να αποσειριοποιήσετε και τέλος τη θέση μέσα στον buffer από όπου θα γίνει η αποσειριοποίηση. Αυτό σας επιτρέπει να αποσειριοποιείτε συγκεκριμένα τμήματα των δεδομένων.

Περπάτησε μέχρι το φωτεινό σημάδι X στον σταθμό εξυπηρέτησης και στρέψου προς το γραφείο. Δημιούργησε τρεις (3) μεταβλητές με ονόματα: integer, float και double. Θα τις χρησιμοποιήσουμε για να επαληθεύσουμε το μέγεθος σε bytes κάθε μορφής μέσω της συνάρτησης struct.calcsize(). Για τη μεταβλητή integer κάλεσε τη συνάρτηση με όρισμα 'i', για τη float με όρισμα 'f' και για τη double με όρισμα 'd'. Για παράδειγμα: integer = struct.calcsize('i'). Πρόσθεσε τις τρεις (3) μεταβλητές στην προ-γραμμένη συνάρτηση write().

Περπάτησε μέχρι το χρυσό σημάδι X και χρησιμοποίησε τη συνάρτηση read() για να συλλέξεις δεδομένα σχετικά με τη νέα αγροτική έκταση. Κατέγραψε τα σημεία δεδομένων και τη μορφή για μελλοντική χρήση, συγκεκριμένα: Resources, Size και Estimate. Μόλις τα καταγράψεις, περπάτησε μέχρι το φωτεινό σημάδι X πάνω στην μπλε μοκέτα και δημιούργησε μια μεταβλητή με όνομα blue_data.

Στη μεταβλητή blue_data αποθήκευσε την τιμή της συνάρτησης struct.pack(), δίνοντας ως ορίσματα τη μορφή και τις τιμές που κατέγραψες προηγουμένως. Κατά τη γραφή της μορφής, πρέπει να «πακετάρεις» τους τύπους μορφής σε μία ενιαία συμβολοσειρά. Για παράδειγμα, η μορφή integer συμβολίζεται 'i' όπως αναφέραμε, αν προσθέτεις τρεις ακέραιους, γράφεις 'iii'. Ομοίως, εάν προσθέτεις έναν ακέραιο, ένα float και ένα double, το γράφεις 'ifd'. Κατά την προσθήκη των δεδομένων, τα τοποθετείς ξεχωριστά ως ορίσματα. Εδώ ένα συνολικό παράδειγμα:

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)

Η συνάρτηση struct.pack() προσφέρει μεγάλη ευελιξία, επιτρέποντάς σου να καθορίζεις πώς θα μορφοποιηθούν τα δεδομένα και να σειριοποιείς πολλαπλά σημεία δεδομένων ταυτόχρονα, σύμφωνα με την κρίση σου. Πρόσθεσε τα δεδομένα που διάβασες προηγουμένως χρησιμοποιώντας το παραπάνω παράδειγμα ως βάση. Χρησιμοποίησε τη συνάρτηση display() με όρισμα το blue_data για να δεις τα πακεταρισμένα δεδομένα.

Περπάτησε μέχρι το σκοτεινό σημάδι X πάνω στην μπλε μοκέτα και στρέψε το βλέμμα σου προς το τερματικό. Δημιούργησε μια μεταβλητή με όνομα blue_unpack και αποθήκευσε την τιμή της συνάρτησης struct.unpack(), δίνοντας ως ορίσματα την ίδια μορφή που χρησιμοποίησες για το πακετάρισμα των δεδομένων και τη μεταβλητή blue_data. Η μορφή γράφεται με τον ίδιο τρόπο όπως στη struct.pack(), έτσι ώστε να μπορείς να αποσειριοποιήσεις τα δεδομένα με τον ίδιο τρόπο που τα σειριοποίησες. Χρησιμοποίησε τη συνάρτηση write() με όρισμα το blue_unpack για να επαληθεύσεις τα δεδομένα που πακέταρες προηγουμένως.

Στην ίδια θέση θα χρησιμοποιήσουμε επίσης τη συνάρτηση struct.iter_unpack(), η οποία δέχεται τα ίδια ακριβώς ορίσματα με τη struct.unpack(), αλλά τώρα μορφοποιείται ως βρόχος for, επιτρέποντάς μας να επαναλάβουμε τα δεδομένα αντί να τα απεικονίσουμε όλα αμέσως. Η συνάρτηση κωδικοποιείται ως εξής:

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

Θα χρησιμοποιήσουμε τη συνάρτηση speak() για να εμφανίσουμε τις τιμές. Για τα ορίσματα που λείπουν στη συνάρτηση struct.iter_unpack(), πρόσθεσε αυτά που χρησιμοποίησες προηγουμένως με τη struct.unpack(), καθώς πρόκειται για παραλλαγές της ίδιας συνάρτησης σε ό,τι αφορά τη χρήση.

Περπάτησε μέχρι το χρυσό σημάδι X πάνω στην κόκκινη μοκέτα και στρέψε το βλέμμα σου προς το γραφείο. Χρησιμοποίησε τη συνάρτηση read() για να ελέγξεις τις ποσότητες των καλλιεργειών. Κατέγραψε όλες τις ποσότητες και τη μορφή για κάθε καλλιέργεια. Περπάτησε μέχρι το φωτεινό σημάδι X πάνω στην κόκκινη μοκέτα και δημιούργησε ένα αντικείμενο με όνομα buffer, αναθέτοντας του την τιμή bytearray(16). Πρόκειται για μια συλλογή byte που μπορούμε να διευθύνουμε πριν την πλήρωσή της, και για τους σκοπούς μας λειτουργεί σαν μια «τράπεζα δεδομένων» όπου μπορούμε να αποθηκεύουμε χειροκίνητα τα δεδομένα. Ο αριθμός 16 ως όρισμα είναι το μήκος σε bytes που μπορούμε να αποθηκεύσουμε στο αντικείμενο buffer.

Χρησιμοποίησε τη συνάρτηση struct.pack_into() για να γεμίσεις το αντικείμενο buffer που δημιούργησες. Δεν χρειάζεται να δημιουργήσεις μια μεταβλητή για να αποθηκεύσεις την τιμή αυτής της συνάρτησης, καθώς η ίδια η συνάρτηση θα εισάγει απευθείας τις τιμές στο αντικείμενο buffer. Θα χρησιμοποιήσουμε τη συνάρτηση για κάθε μία από τις τιμές που σημείωσες προηγουμένως και θα συμπληρώσουμε τα ορίσματά της με αυτές.

Για παράδειγμα, για την πρώτη παρεχόμενη τιμή καλλιέργειας, θα σου δοθεί η μορφή της, η θέση της σε bytes και η ποσότητά της. Στο πρώτο όρισμα γράψε τη μορφή, στο δεύτερο το buffer στο οποίο θέλεις να σειριοποιήσεις τα bytes, στην προκειμένη περίπτωση το buffer. Στο τρίτο όρισμα όρισε τη θέση μέσα στο buffer όπου θέλεις να τοποθετηθεί η τιμή – η μορφή καθορίζει πόσα bytes θα καταλάβει, οπότε φρόντισε να μην καλύψεις ήδη κατεχόμενες θέσεις. Τέλος, πρόσθεσε την τιμή που θέλεις να σειριοποιήσεις και να πακετάρεις στο αντικείμενο buffer.

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

Το αντικείμενο buffer έχει 16 bytes όπως αναφέραμε προηγουμένως. Στον παραπάνω κώδικα, η μορφή integer καταλαμβάνει 4 bytes και εισάγεται στη θέση 0. Αυτό σημαίνει πως μόλις εισαχθεί η τιμή στο buffer, απομένουν μόνο 12 ελεύθερα bytes, αφού οι θέσεις 03 έχουν καταληφθεί από την τιμή 82. Κάνε το ίδιο για όλα τα τρία (3) σημεία δεδομένων των καλλιεργειών που διάβασες και κατέγραψες. Χρησιμοποίησε τη συνάρτηση display() με όρισμα το buffer για να εμφανίσεις τα σειριοποιημένα δεδομένα.

Περπάτησε μέχρι το σκοτεινό σημάδι X πάνω στην κόκκινη μοκέτα και στρέψε το βλέμμα σου προς το τερματικό. Εδώ θα αποσειριοποιήσουμε τα δεδομένα για να επαληθεύσουμε το περιεχόμενο και να διασφαλίσουμε τη σωστή αποθήκευση. Δημιούργησε τρεις μεταβλητές με ονόματα: lettuce, carrots και melons. Θα αποσειριοποιήσουμε τα δεδομένα κάθε σημείου ξεχωριστά. Για καθεμία από τις μεταβλητές αποθήκευσε την τιμή της συνάρτησης struct.unpack_from(), δίνοντας ως ορίσματα τα ίδια δεδομένα που χρησιμοποίησες για το πακετάρισμα. Στο πρώτο όρισμα βάλε τη μορφή, στο δεύτερο το αντικείμενο buffer από όπου θα αποσειριοποιήσεις και στο τρίτο τη θέση μέσα στο buffer από όπου θέλεις να κάνεις την αποσειριοποίηση. Για παράδειγμα:

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

Αυτά τα δεδομένα αντιστοιχούν στο προηγούμενο παράδειγμα πακεταρίσματος και τώρα απο-πακετάρονται. Κάνε το ίδιο για τις άλλες δύο μεταβλητές και πέρασε τις lettuce, carrots και melons στην προ-γραμμένη συνάρτηση write() για να ολοκληρώσεις το επίπεδο.

Βιβλίο Κώδικα