array — Secuencia de datos de tipo fijo

Propósito:Administrar secuencias de datos de tipo fijo de manera eficiente

El módulo array define una estructura de datos de secuencia que se ve muy parecida a una list, excepto que todos los miembros tienen que ser del mismo tipo primitivo. Los tipos admitidos son todos numéricos u otros tipos primitivos de tamaño fijo como bytes.

Consulta la the table below para algunos de los tipos soportados. La documentación estándar de la biblioteca para array incluye una lista completa de códigos de tipo.

Códigos de tipo para miembros de la matriz
Código Tipo Tamaño mínimo (bytes)
b int 1
B int 1
h signed short 2
H unsigned short 2
i signed int 2
I unsigned int 2
l signed long 4
L unsigned long 4
q signed long long 8
Q unsigned long long 8
f float 4
d double float 8

Inicialización

Un array se crea con un argumento que describe el tipo de los datos a ser permitidos, y posiblemente una secuencia inicial de datos para almacenar en la matriz.

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))

En este ejemplo, la matriz está configurada para contener una secuencia de bytes y se inicializa con una cadena de bytes simple.

$ 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'

Manipulando Arrays

Un array puede extenderse y manipularse en de la misma manera que otras secuencias de 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)))

Las operaciones compatibles incluyen cortar, iterar y agregar elementos hasta al final.

$ 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)]

Arrays y archivos

El contenido de una matriz puede escribirse y leerse de archivos usando métodos incorporados programadoes eficientemente para ese propósito.

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)

Este ejemplo ilustra la lectura de los datos «en bruto», es decir, directamente del archivo binario, en lugar de leerlo en una nueva matriz y convertir los bytes a los tipos apropiados.

$ 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() usa tobytes() para formatear los datos, y fromfile() utiliza frombytes() para convertirlo nuevamente a una instancia de matriz.

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)

Ambos tobytes() y frombytes() funcionan en cadenas de bytes, no cadenas Unicode.

$ python3 array_tobytes.py

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

Orden de bytes alternativo

Si los datos en la matriz no están en el orden nativo de bytes, o si los datos necesitan ser intercambiados antes de ser enviados a un sistema con un orden de bytes diferente (o en la red), es posible convertir toda la matriz sin iterar sobre los elementos en Python.

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))

El método byteswap() cambia el orden de bytes de los elementos en la matriz en C, por lo que es mucho más eficiente que el bucle sobre los datos en 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

Ver también