Ist Python haben einen bitfield Typ?
-
02-07-2019 - |
Frage
Ich brauche eine kompakte Darstellung eines Arrays von booleans, ist Python einen eingebauten bitfield Typ oder werde ich eine alternative Lösung finden muß?
Lösung
BitArray war die beste Antwort, die ich gefunden, wenn ich ein ähnliches Bedürfnis vor kurzem hatte. Es ist eine C-Erweiterung (so viel schneller als Bitvektor, die reine Python ist) und speichert seine Daten in einem tatsächlichen bitfield (es ist also acht Mal mehr Speicher effizienter als ein numpy boolean-Array, das ein Byte pro Element verwendet wird.)
Andere Tipps
Wenn Sie in erster Linie in der Lage sein wollen, um Ihre Bit-Felder zu benennen und sie leicht zu manipulieren, zum Beispiel mit Fahnen als einzelne Bits in einem Kommunikationsprotokoll dargestellt zu arbeiten, dann können Sie die Standardstruktur und Union Features von ctypes , wie unter
Sie sollten einen Blick auf dem bitstring -Modul, das vor kurzer Version 2.0 erreicht hat .
Die binären Daten werden kompakt als Byte-Array gespeichert und einfach erstellt werden können, modifiziert und analysiert. Sie können Sie können dann analysieren und sie mit einfachen Funktionen oder Slice-Notation ändern -. Keine Notwendigkeit, sich Sorgen zu machen über Bitmasken etc Es gibt auch ein Konzept einer Bit-Position, so dass Sie es wie eine Datei behandeln können oder streamen, wenn das für Dich nützlich ist. Die Eigenschaften werden verwendet, um unterschiedliche Interpretationen der Bit-Daten zu geben. Außerdem gibt es Unterstützung für die Standard-bitweise binären Operatoren, Verpackung, Auspacken, endianness und vieles mehr. Die neueste Version ist für Python 2.7 und 3.x, und obwohl es rein ist Python es ist recht gut in Bezug auf Speicher und Geschwindigkeit optimiert. BitString
Objekte aus Binär-, hex, ganze Zahlen (groß oder Little-Endian), Streicher, Bytes, Schwimmern, Dateien und vieles mehr. a = BitString('0xed44')
b = BitString('0b11010010')
c = BitString(int=100, length=14)
d = BitString('uintle:16=55, 0b110, 0o34')
e = BitString(bytes='hello')
f = pack('<2H, bin:3', 5, 17, '001')
a.prepend('0b110')
if '0b11' in b:
c.reverse()
g = a.join([b, d, e])
g.replace('0b101', '0x3400ee1')
if g[14]:
del g[14:17]
else:
g[55:58] = 'uint:11=33, int:9=-1'
w = g.read(10).uint
x, y, z = g.readlist('int:4, int:4, hex:32')
if g.peek(8) == '0x00':
g.pos += 10
Ich benutze die binären bitweise Operatoren &, |! ^, >> und <<. Sie arbeiten wirklich gut und werden direkt in der zugrunde liegenden C implementiert, die auf der zugrunde liegenden Hardware in der Regel direkt ist.
Sie sind jede Ihrer Werte als Zweierpotenz:
testA = 2**0
testB = 2**1
testC = 2**3
Sie dann einen Wert setzen true:
table = table | testB
ein Wert false ein:
table = table & (~testC)
für einen Wert testen:
bitfield_length = 0xff
if ((table & testB & bitfield_length) != 0):
print "Field B set"
ein wenig tiefer in hexadezimale Darstellung Dig, wenn dies nicht Sinn machen. Dies ist im Grunde, wie Sie den Überblick über Ihren boolean Flags in einer eingebetteten C-Anwendung halten als auch (wenn Sie limitted Speicher haben).
Das Bitvektor Paket kann sein, was Sie brauchen. Es ist nicht in meiner Python-Installation gebaut, aber leicht auf der Python-Website aufzuspüren.
https://pypi.python.org/pypi/BitVector für die aktuelle Version .
NumPy hat einen Array Schnittstelle Modul, das Sie eine bitfield machen verwenden können.
Wenn Ihr bitfield kurz ist, können Sie wahrscheinlich die Struktur Modul . Sonst würde ich so etwas wie ein Wrapper um der Array-Modul empfehlen.
Auch dann, wenn das ctypes Modul enthalten bitfields , aber ich habe es mir nie. Caveat emptor .
Wenn Sie verwenden Ints wollen (oder lange Ints) als Arrays von bools darzustellen (oder als Mengen von ganzen Zahlen), werfen Sie einen Blick auf http://sourceforge.net/projects/pybitop/files/
Es bietet Insert / Auszug bitfields in langen Ints; Suche nach der höchstwertigen oder niedrigstwertigen ‚1‘ Bit; Zählen alle 1'en; Bit-Umkehr; Sachen wie das, was alles möglich in reinem Python ist aber viel schneller in C.
Für meist aufeinanderfolgende Bits gibt es die https://pypi.org/project/range_set/ Modul, das API kompatibel zu Python eingebauter in set
ist. Wie der Name schon sagt, speichert es die Bits als Beginn / Ende-Paare.