Khóa học Phát triển Python Nâng cao
Chương
>
Cấp độ

Các mô-đun tuần tự hóa
Mô-đun Struct

Mục tiêu

Thiết lập phân tích dữ liệu cuối cùng cho vùng đất nông nghiệp mới sử dụng module struct.

Cuối con đường có một trạm dịch vụ quản lý vùng đất nông nghiệp mới đã xây dựng và cây trồng đã được trồng. Tại đây chúng ta sẽ kiểm tra và xử lý dữ liệu cho cây trồng đã được trồng và sản lượng dự kiến của vùng đất. Giống như các cấp độ khác trong chương này, chúng ta sẽ làm việc với tuần tự hóa và giải tuần tự hóa dữ liệu, giới thiệu một module cuối cùng tên là struct.

Module struct giới thiệu một loạt các hàm tuần tự hóa đóng gói dữ liệu ở định dạng nhị phân, không giống các module khác chúng ta đã làm việc, tuy nhiên bạn có quyền kiểm soát cao hơn cách chúng ta cấu trúc dữ liệu cả khi đóng gói và sau khi giải đóng gói, làm cho nó linh hoạt hơn. Dùng import struct để truy cập các hàm sau mà chúng ta sẽ sử dụng để xử lý dữ liệu:

  • struct.calcsize(): Xác định có bao nhiêu byte được đóng gói cho chuỗi định dạng cho trước, nó nhận một (1) đối số là định dạng mà bạn muốn xác minh kích thước byte của nó. Các định dạng chúng ta sẽ sử dụng bao gồm:
    • integer: được ký hiệu là 'i' là định dạng cho dữ liệu dạng số nguyên
    • float: được ký hiệu là 'f' là định dạng cho dữ liệu dạng số thập phân
    • double: được ký hiệu là 'd' là định dạng cho dữ liệu dạng số thập phân phức tạp hơn, nơi định dạng float là không đủ
  • struct.pack(): Tuần tự hóa dữ liệu sang nhị phân, đóng gói theo định dạng bạn lựa chọn. Nó có thể nhận hai (2) hoặc nhiều hơn đối số, gồm định dạng bạn muốn sử dụng và các giá trị bạn muốn tuần tự hóa. Các định dạng là những cái đã nêu ở trên và bạn phải thêm chúng tương ứng với số lượng đối số bạn thêm.
  • struct.unpack(): Giải tuần tự hóa dữ liệu nhị phân đã đóng gói, nhận hai (2) đối số, định dạng mà nó cần tương thích với định dạng đã đóng gói, và đối số thứ hai là dữ liệu đã được đóng gói.
  • struct.iter_unpack(): Giải tuần tự hóa dữ liệu nhị phân đã đóng gói, hoạt động giống struct.unpack() nhưng lặp lại qua từng khối dữ liệu riêng lẻ thông qua vòng lặp.
  • struct.pack_into(): Phiên bản nâng cao của struct.pack(), nhận bốn (4) đối số gồm định dạng bạn muốn sử dụng, bộ đệm dữ liệu bạn muốn chèn dữ liệu vào, vị trí trong buffer bạn muốn chèn dữ liệu, và cuối cùng là dữ liệu bạn đóng gói.
  • struct.unpack_from(): Phiên bản nâng cao của struct.unpack(), nhận ba (3) đối số: định dạng bạn muốn sử dụng, bộ đệm dữ liệu bạn muốn giải đóng gói và vị trí trong buffer bạn muốn giải đóng gói từ đó. Điều này cho phép bạn giải đóng gói các phần cụ thể của dữ liệu.

Đi đến dấu X sáng ở trạm dịch vụ và đối diện bàn, tạo ba (3) biến tên là: integer, floatdouble. Chúng ta sẽ dùng những biến này để xác minh kích thước byte của mỗi định dạng bằng cách sử dụng hàm struct.calcsize(). Đối với biến integer, dùng hàm với đối số 'i', đối với biến float dùng hàm với đối số 'f' và cuối cùng biến double dùng với đối số 'd'. Ví dụ: integer = struct.calcsize('i'). Thêm ba (3) biến này vào hàm write() đã được viết sẵn.

Đi đến dấu X vàng và dùng hàm read() để thu thập dữ liệu về vùng đất mới, ghi chú các điểm dữ liệu và định dạng để sử dụng sau này, cụ thể: Resources, SizeEstimate. Sau khi ghi chú, quay lại dấu X sáng trên thảm xanh và tạo một biến tên là blue_data.

Với biến blue_data, lưu giá trị trả về của hàm struct.pack(), dùng định dạng và các giá trị bạn đã ghi chú trước đó làm đối số. Khi viết định dạng, bạn phải "đóng gói" các kiểu định dạng thành một đơn vị duy nhất. Ví dụ, định dạng integer được ký hiệu 'i' như đã nêu, nếu bạn thêm ba kiểu integer, bạn viết chúng là 'iii'. Tương tự, nếu bạn thêm một integer, một float và một double, nó sẽ được viết 'ifd'. Khi thêm dữ liệu, bạn đặt chúng lần lượt làm đối số. Dưới đây là ví dụ tổng quát:

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)

Hàm struct.pack() cho phép rất nhiều tùy chọn, cho phép bạn định dạng dữ liệu theo ý muốn và tuần tự hóa nhiều điểm dữ liệu cùng lúc, theo quyết định của bạn. Thêm dữ liệu đã đọc trước đó sử dụng ví dụ trên làm cơ sở. Dùng hàm display() với blue_data làm đối số để xem dữ liệu đã đóng gói.

Đi đến dấu X tối trên thảm xanh và đối diện máy trạm, tạo một biến tên blue_unpack và lưu giá trị trả về của hàm struct.unpack(), dùng cùng định dạng đã dùng để đóng gói dữ liệu và biến blue_data làm đối số. Định dạng viết giống cách dùng với struct.pack(), để bạn có thể giải dữ liệu theo cùng cách bạn đã đóng gói ban đầu. Dùng hàm write() với blue_unpack làm đối số để xác minh dữ liệu bạn đã đóng gói trước đó.

Tại cùng vị trí đó, chúng ta cũng sẽ dùng hàm struct.iter_unpack(), nó nhận các đối số giống hệt struct.unpack() nhưng được đóng gói trong vòng lặp for, cho phép chúng ta lặp qua dữ liệu thay vì chỉ viết ra hết. Hàm được viết như sau:

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

Chúng ta sẽ dùng hàm speak() để hiển thị các giá trị, đối với các đối số thiếu trong hàm struct.iter_unpack(), thêm cùng các đối số bạn đã dùng với struct.unpack() vì chúng là biến thể về cách dùng của cùng một hàm.

Đi đến dấu X vàng trên thảm đỏ và đối diện bàn, dùng hàm read() để xem lại số lượng cây trồng. Ghi chú tất cả số lượng và định dạng cho mỗi loại cây. Đi đến dấu X sáng trên thảm đỏ và tạo một đối tượng tên buffer, gán giá trị bytearray(16). Đây là một tập hợp các byte mà chúng ta có thể truy cập trước khi điền dữ liệu, về cơ bản nó giống như một kho dữ liệu nơi bạn có thể lưu trữ dữ liệu thủ công. Số 16 làm đối số là độ dài của số byte bạn có thể lưu trong đối tượng buffer.

Dùng hàm struct.pack_into() để điền dữ liệu vào đối tượng buffer bạn đã tạo. Không cần tạo biến lưu giá trị của hàm vì hàm sẽ chèn trực tiếp giá trị vào buffer. Chúng ta sẽ dùng hàm này cho mỗi giá trị đã ghi chú và điền vào các đối số tương ứng.

Ví dụ, đối với giá trị cây trồng đầu tiên, bạn sẽ được cung cấp định dạng, vị trí byte và số lượng. Thêm định dạng làm đối số đầu tiên, buffer làm đối số thứ hai. Đối số thứ ba là vị trí bạn muốn ghi giá trị vào buffer, định dạng sẽ quyết định số byte sử dụng, vì vậy hãy đảm bảo đóng gói dữ liệu vào những vị trí chưa bị chiếm. Cuối cùng thêm giá trị bạn muốn tuần tự hóa và đóng gói vào buffer.

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

Đối tượng buffer16 byte như đã nêu, trong đoạn mã trên, định dạng integer chiếm 4 byte và được chèn tại vị trí 0. Điều này có nghĩa là sau khi dữ liệu được chèn, sẽ còn 12 byte trong buffer chưa được sử dụng, vị trí 0-3 đã bị chiếm bởi giá trị 82. Thực hiện điều này cho cả ba (3) điểm dữ liệu cây trồng đã ghi chú. Dùng hàm display() với buffer làm đối số để hiển thị dữ liệu đã đóng gói.

Đi đến dấu X tối trên thảm đỏ và đối diện máy trạm, tại đây chúng ta sẽ giải tuần tự hóa dữ liệu để xác minh nội dung và đảm bảo lưu trữ đúng. Tạo ba biến tên là: lettuce, carrotsmelons, ta sẽ giải tuần tự hóa từng điểm dữ liệu riêng. Đối với mỗi biến, lưu giá trị trả về của struct.unpack_from() với các đối số sử dụng cùng dữ liệu bạn đã ghi chú để đóng gói. Đối số đầu tiên là định dạng, đối số thứ hai là đối tượng buffer là nơi giải đóng gói, và cuối cùng là vị trí trong buffer bạn muốn giải. Ví dụ:

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

Dữ liệu này tương ứng với ví dụ đóng gói trước đó đang được giải, làm tương tự cho hai biến còn lại và đưa lettuce, carrotsmelons vào hàm write() đã được viết sẵn để hoàn thành cấp độ.

Sách Mã