array - Liste bestehend aus Elementen nicht änderbarer Daten

Link zu Doug Hellmanns Original Artikel vom 09. November 2008

Zweck: Effizienter Umgang mit Sequenzen, die aus unveränderlichen Elementen bestehen
Python: ab 1.4

Das array Modul definiert eine Listenstruktur die große Ähnlichkeit mit einer list hat, außer das alle Elemente vom gleichen Datentyp sein müssen. Die unterstützten Datentypen sind in der Standard Library Dokumentation zu finden. Sie sind alle numerisch beziehungsweise unveränderliche Datentypen wie zum Beispiel bytes.

Array Initialisierung

Ein array wird durch die Übergabe eines Parameters, welcher den Datentyp definiert, initialisiert und durch die optionalen Übergabe einer Liste.

import array
import binascii

s = 'This is the array.'
a = array.array('c', s)

print 'Als string:', s
print 'Als array :', a
print 'Als Hex-Zahl   :', binascii.hexlify(a)

In diesem Beispiel erwartet das array eine Sequenz von Bytes und es wird mit einem einfachen String initialisiert.

$ python array_string.py
Als string: This is the array.
Als array : array('c', [84, 104, 105, 115, 32, 105, 115,32, 116, 104, 101, 32, 97, 114, 114, 97, 121, 46])
Als Hex-Zahl : 54686973206973207468652061727261792e

Manipulation von Arrays

Ein array kann wie jede andere Python Sequenz erweitert und manipuliert werden.

import array

a = array.array('i', xrange(5))
print 'Initialwert :', a

a.extend(xrange(5))
print 'Erweitert:', a

print 'Slice   :', a[3:6]

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

$ python array_sequence.py
Initialwert : array('i', [0, 1, 2, 3, 4])
Erweitert: array('i', [0, 1, 2, 3, 4, 0, 1, 2, 3, 4])
Slice : array('i', [3, 4, 0])
Iterator: [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 0), (6, 1), (7, 2), (8, 3), (9, 4)]

Arrays und Dateien

Der Inhalt von Arrays kann aus Dateien gelesen und geschrieben werden. Hierzu werden eingebaute Methoden verwendet, die speziell für diesen Zweck entwickelt wurden.

import array
import binascii
import tempfile

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

# Schreibt das Array aus Zahlen in eine Datei
output = tempfile.NamedTemporaryFile()
a.tofile(output.file) # must pass an *actual* file
output.flush()

# Liest die Rohdaten
input = open(output.name, 'rb')
raw_data = input.read()
print 'Rohdaten:', binascii.hexlify(raw_data)

# Liest die Daten in ein array
input.seek(0)
a2 = array.array('i')
a2.fromfile(input, len(a))
print 'A2:', a2

Dieses Beispiel illustriert das Lesen der Rohdaten direkt aus der Binärdatei, anstatt sie in ein array einzulesen und die Bytes dann in die passenden Datentypen zu konvertieren.

$ python array_file.py
A1: array('i', [0, 1, 2, 3, 4])
Rohdaten: 0000000001000000020000000300000004000000
A2: array('i', [0, 1, 2, 3, 4])

Alternative Byte-Reihenfolge

Wenn die Daten im Array nicht in der natürlichen Byte-Reihenfolge vorliegen oder getauscht werden müssen ehe sie, für ein anderes System mit abweichender Byte-Reihenfolge, in eine Datei geschrieben werden, so ist es einfach ein vollständiges Array zu konvertieren ohne über die einzelnen Elemente mittels Python zu iterieren.

import array
import binascii

def to_hex(a):
    chars_per_item = a.itemsize * 2 # 2 hexadezimale Zahlen
    hex_version = binascii.hexlify(a)
    num_chunks = len(hex_version) / chars_per_item
    for i in xrange(num_chunks):
        start = i*chars_per_item
        end = start + chars_per_item
        yield hex_version[start:end]

a1 = array.array('i', xrange(5))
a2 = array.array('i', xrange(5))
a2.byteswap()

fmt = '%10s %10s %10s %10s'
print fmt % ('A1 hex', 'A1', 'A2 hex', 'A2')
print fmt % (('-' * 10,) * 4)
for values in zip(to_hex(a1), a1, to_hex(a2), a2):
    print fmt % values

    $ python array_byteswap.py
A1 hex A1 A2 hex A2 ---------- ---------- ---------- ---------- 00000000 0 00000000 0 01000000 1 00000001 16777216 02000000 2 00000002 33554432 03000000 3 00000003 50331648 04000000 4 00000004 67108864