Рубрики
Без рубрики

array – Последовательность данных фиксированного типа

Автор оригинала: Doug Hellmann.

Цель:

Эффективно управляйте последовательностями числовых данных фиксированного типа.

Модуль array определяет структуру данных последовательности, которая очень похожа на list , за исключением того, что все элементы должны быть одного и того же примитивного типа. Поддерживаются все числовые или другие примитивные типы фиксированного размера, например байты.

В таблице ниже указаны некоторые из поддерживаемых типов. Документация стандартной библиотеки для array включает полный список кодов типов.

Коды типов для членов массива

Код

Тип

Минимальный размер (байты)

int

int

подписанный короткий

беззнаковый короткий

подписанный int

беззнаковое целое

подписан долго

беззнаковый длинный

подписан долго

беззнаковый длинный длинный

плавать

двойной поплавок

Инициализация

Экземпляр array создается с аргументом, описывающим тип данных, которые должны быть разрешены, и, возможно, начальную последовательность данных для хранения в массиве.

array_string.py

import array
import binascii

s  b'This is the array.'
a  array.array('b', s)

print('As byte string:', s)
print('As array      :', a)
print('As hex        :', binascii.hexlify(a))

В этом примере массив сконфигурирован для хранения последовательности байтов и инициализируется простой байтовой строкой.

$ python3 array_string.py

As byte string: b'This is the array.'
As array      : array('b', [84, 104, 105, 115, 32, 105, 115, 32,
 116, 104, 101, 32, 97, 114, 114, 97, 121, 46])
As hex        : b'54686973206973207468652061727261792e'

Управление массивами

array можно расширять и манипулировать другими способами так же, как и другими последовательностями Python.

array_sequence.py

import array
import pprint

a  array.array('i', range(3))
print('Initial :', a)

a.extend(range(3))
print('Extended:', a)

print('Slice   :', a[2:5])

print('Iterator:')
print(list(enumerate(a)))

Поддерживаемые операции включают нарезку, повторение и добавление элементов в конец.

$ python3 array_sequence.py

Initial : array('i', [0, 1, 2])
Extended: array('i', [0, 1, 2, 0, 1, 2])
Slice   : array('i', [2, 0, 1])
Iterator:
[(0, 0), (1, 1), (2, 2), (3, 0), (4, 1), (5, 2)]

Массивы и файлы

Содержимое массива можно записывать в файлы и считывать из них с помощью встроенных методов, эффективно закодированных для этой цели.

array_file.py

import array
import binascii
import tempfile

a  array.array('i', range(5))
print('A1:', a)

# Write the array of numbers to a temporary file
output  tempfile.NamedTemporaryFile()
a.tofile(output.file)  # must pass an *actual* file
output.flush()

# Read the raw data
with open(output.name, 'rb') as input:
    raw_data  input.read()
    print('Raw Contents:', binascii.hexlify(raw_data))

    # Read the data into an array
    input.seek(0)
    a2  array.array('i')
    a2.fromfile(input, len(a))
    print('A2:', a2)

Этот пример иллюстрирует чтение «сырых» данных, то есть непосредственно из двоичного файла, по сравнению с чтением их в новый массив и преобразованием байтов в соответствующие типы.

$ python3 array_file.py

A1: array('i', [0, 1, 2, 3, 4])
Raw Contents: b'0000000001000000020000000300000004000000'
A2: array('i', [0, 1, 2, 3, 4])

tofile () использует tobytes () для форматирования данных, а fromfile () использует frombytes () для преобразования его обратно в экземпляр массива.

array_tobytes.py

import array
import binascii

a  array.array('i', range(5))
print('A1:', a)

as_bytes  a.tobytes()
print('Bytes:', binascii.hexlify(as_bytes))

a2  array.array('i')
a2.frombytes(as_bytes)
print('A2:', a2)

И tobytes () , и frombytes () работают с байтовыми строками, а не с строками Unicode.

$ python3 array_tobytes.py

A1: array('i', [0, 1, 2, 3, 4])
Bytes: b'0000000001000000020000000300000004000000'
A2: array('i', [0, 1, 2, 3, 4])

Альтернативный порядок байтов

Если данные в массиве находятся не в собственном порядке байтов или если данные необходимо поменять местами перед отправкой в систему с другим порядком байтов (или по сети), можно преобразовать весь массив без

array_byteswap.py

import array
import binascii


def to_hex(a):
    chars_per_item  a.itemsize * 2  # 2 hex digits
    hex_version  binascii.hexlify(a)
    num_chunks  len(hex_version) // chars_per_item
    for i in range(num_chunks):
        start  i * chars_per_item
        end  start + chars_per_item
        yield hex_version[start:end]


start  int('0x12345678', 16)
end  start + 5
a1  array.array('i', range(start, end))
a2  array.array('i', range(start, end))
a2.byteswap()

fmt  '{:>12} {:>12} {:>12} {:>12}'
print(fmt.format('A1 hex', 'A1', 'A2 hex', 'A2'))
print(fmt.format('-' * 12, '-' * 12, '-' * 12, '-' * 12))
fmt  '{!r:>12} {:12} {!r:>12} {:12}'
for values in zip(to_hex(a1), a1, to_hex(a2), a2):
    print(fmt.format(*values))

Метод byteswap () переключает порядок байтов элементов в массиве изнутри C, поэтому он намного эффективнее, чем цикл данных в Python.

$ python3 array_byteswap.py

      A1 hex           A1       A2 hex           A2
------------ ------------ ------------ ------------
 b'78563412'    305419896  b'12345678'   2018915346
 b'79563412'    305419897  b'12345679'   2035692562
 b'7a563412'    305419898  b'1234567a'   2052469778
 b'7b563412'    305419899  b'1234567b'   2069246994
 b'7c563412'    305419900  b'1234567c'   2086024210

Смотрите также