Est-ce que Python a un type bitfield?

j'ai besoin d'une représentation compacte d'un tableau de booléens, Python a-t-il un type bitfield intégré ou Ai-je besoin de trouver une solution alternative?

41
demandé sur martineau 2008-09-27 06:47:40

9 réponses

Bitarray était la meilleure réponse que j'ai trouvée, quand j'ai récemment eu un besoin similaire. C'est une extension C (donc beaucoup plus rapide que BitVector, qui est Python pur) et stocke ses données dans un bitfield réel (donc c'est huit fois plus efficace en mémoire qu'un tableau booléen numpy, qui semble utiliser un octet par élément.)

27
répondu Alex Coventry 2008-09-27 08:20:43

si vous voulez principalement être capable de nommer vos champs de bits et de les manipuler facilement, par exemple pour travailler avec des drapeaux représentés comme des bits simples dans un protocole de communication, alors vous pouvez utiliser la Structure standard et les fonctionnalités D'Union de ctypes , comme décrit à Comment puis-je déclarer correctement une Structure ctype + Union en Python? - Débordement De La Cheminée

par exemple, pour travailler avec les 4 bits les moins significatifs d'un octet individuellement, il suffit de les nommer du plus petit au plus important dans une structure de Littleendians. Vous utilisez une union pour fournir l'accès aux mêmes données qu'un byte ou int de sorte que vous pouvez déplacer les données dans ou hors du protocole de communication. Dans ce cas, cela se fait via le champ flags.asbyte :

import ctypes
c_uint8 = ctypes.c_uint8

class Flags_bits(ctypes.LittleEndianStructure):
    _fields_ = [
            ("logout", c_uint8, 1),
            ("userswitch", c_uint8, 1),
            ("suspend", c_uint8, 1),
            ("idle", c_uint8, 1),
        ]

class Flags(ctypes.Union):
    _fields_ = [("b", Flags_bits),
                ("asbyte", c_uint8)]

flags = Flags()
flags.asbyte = 0xc

print(flags.b.idle)
print(flags.b.suspend)
print(flags.b.userswitch)
print(flags.b.logout)

les quatre bits (que j'ai imprimés ici en commençant par le plus significatif, ce qui semble plus naturel lors de l'impression) sont 1, 1, 0, 0, i.e. 0xc en binaire.

29
répondu nealmcb 2017-05-23 10:31:30

vous devriez jeter un oeil au module bitstring , qui a récemment atteint la version 2.0. Les données binaires sont stockées de manière compacte sous forme de tableau d'octets et peuvent être facilement créées, modifiées et analysées.

vous pouvez créer des objets BitString à partir de binaire, octal, hex, entiers (grand ou petit endian), chaînes, octets, floats, fichiers et plus.

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

vous pouvez alors les analyser et les modifier avec des fonctions simples ou notation de tranche - pas besoin de se soucier des masques de bits, etc.

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'

il y a aussi un concept de position de bit, de sorte que vous pouvez le traiter comme un fichier ou un flux si cela vous est utile. Les propriétés sont utilisées pour donner différentes interprétations des données de bits.

w = g.read(10).uint
x, y, z = g.readlist('int:4, int:4, hex:32')
if g.peek(8) == '0x00':
    g.pos += 10

Plus il y a le soutien pour les opérateurs binaires standard bit-wise, l'emballage, le déballage, l'endianness et plus. La dernière version est pour Python 2.7 et 3.x, et, bien que ce Python pur il est raisonnablement bien optimisé en termes de mémoire et de vitesse.

12
répondu Scott Griffiths 2018-02-07 15:10:36

j'utilise les opérateurs bit-wise binaires !, &, |, ^, >>, et <<. Ils fonctionnent vraiment bien et sont implémentés directement dans le C sous-jacent, qui est généralement directement sur le matériel sous-jacent.

6
répondu S.Lott 2008-09-27 13:26:06

représentent chacune de vos valeurs comme une puissance de deux:

testA = 2**0
testB = 2**1
testC = 2**3

ensuite pour définir une valeur true:

table = table | testB

pour définir une valeur false:

table = table & (~testC)

pour tester une valeur:

bitfield_length = 0xff
if ((table & testB & bitfield_length) != 0):
    print "Field B set"

creusez un peu plus dans la représentation hexadécimale si cela n'a pas de sens pour vous. C'est essentiellement la façon dont vous gardez la trace de vos drapeaux booléens dans une application c intégrée ainsi (si vous avez limitted de mémoire).

6
répondu MattG 2008-11-05 15:30:33

le paquet BitVector peut être ce dont vous avez besoin. Il n'est pas intégré à mon installation python, mais il est facile de le retrouver sur le site python.

https://pypi.python.org/pypi/BitVector pour la version actuelle.

5
répondu JasonTrue 2014-11-03 18:46:05

num Py possède un module array interface que vous pouvez utiliser pour créer un bitfield.

4
répondu Jason Baker 2008-09-27 02:52:13

si votre bitfield est court, vous pouvez probablement utiliser le module struct . Sinon, je recommanderais une sorte d'enveloppe autour de le module de réseau .

aussi, le module ctypes contient bitfields , mais je ne l'ai jamais utilisé moi-même. Caveat emptor .

2
répondu Antti Rasinen 2008-09-27 08:41:05

si vous voulez utiliser des ints (ou des longs ints) pour représenter des tableaux de bools( ou des ensembles d'entiers), jetez un oeil à http://sourceforge.net/projects/pybitop/files/

insérer/extraire des bitfields en long ints; la conclusion la plus importante ou moins importante " 1 " bit; en comptant tous les 1; bit d'inversion; des trucs comme ça qui est possible dans le plus pur python, mais beaucoup plus rapide en C.

1
répondu greggo 2010-09-16 21:01:07