Pregunta

Necesito una representación compacta de una matriz de booleanos, ¿Python tiene un tipo de campo de bits incorporado o tendré que encontrar una solución alternativa?

¿Fue útil?

Solución

Bitarray fue la mejor respuesta que encontré, cuando recientemente tuve una necesidad similar. Es una extensión C (mucho más rápida que BitVector, que es Python puro) y almacena sus datos en un campo de bits real (por lo que es ocho veces más eficiente en memoria que una matriz booleana numpy, que parece usar un byte por elemento).

Otros consejos

Si principalmente desea poder nombrar sus campos de bits y manipularlos fácilmente, p. para trabajar con banderas representadas como bits individuales en un protocolo de comunicaciones, puede usar las características estándar de Estructura y Unión de ctypes , como se describe en ¿Cómo declaro correctamente una estructura ctype + Unión en Python? - Desbordamiento de pila

Por ejemplo, para trabajar con los 4 bits menos significativos de un byte individualmente, solo nómbrelos de menor a mayor importancia en una LittleEndianStructure. Utiliza una unión para proporcionar acceso a los mismos datos que un byte o int para que pueda mover los datos dentro o fuera del protocolo de comunicación. En este caso, esto se realiza a través del campo 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)

Los cuatro bits (que he impreso aquí comenzando por el más significativo, que parece más natural al imprimir) son 1, 1, 0, 0, es decir, 0xc en binario.

Debería echar un vistazo al módulo bitstring , que recientemente alcanzó la versión 2.0 . Los datos binarios se almacenan de forma compacta como una matriz de bytes y se pueden crear, modificar y analizar fácilmente.

Puede crear objetos BitString desde binarios, octales, hexadecimales, enteros (endian grande o pequeño), cadenas, bytes, flotantes, archivos y más.

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 continuación, puede analizarlos y modificarlos con funciones simples o notación de corte, sin tener que preocuparse por las máscaras 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'

También hay un concepto de una posición de bit, para que pueda tratarlo como un archivo o una transmisión si eso es útil para usted. Las propiedades se utilizan para dar diferentes interpretaciones de los datos 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

Además, hay soporte para los operadores binarios estándar en cuanto a bits, empaque, desempaque, endianness y más. La última versión es para Python 2.7 y 3.x, y aunque es Python puro, está razonablemente bien optimizado en términos de memoria y velocidad.

¡Utilizo los operadores binarios en cuanto a bits!, & amp ;, |, ^, > > ;, y < < ;. Funcionan realmente bien y se implementan directamente en el C subyacente, que generalmente está directamente en el hardware subyacente.

Representa cada uno de tus valores como una potencia de dos:

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

Luego, para establecer un valor verdadero:

table = table | testB

Para establecer un valor falso:

table = table & (~testC)

Para probar un valor:

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

Profundice un poco más en la representación hexadecimal si esto no tiene sentido para usted. Básicamente, así es como realiza un seguimiento de sus indicadores booleanos en una aplicación C incrustada (si tiene memoria limitada).

El paquete BitVector puede ser lo que necesita. No está integrado en mi instalación de Python, pero es fácil de rastrear en el sitio de Python.

https://pypi.python.org/pypi/BitVector para la versión actual .

NumPy tiene un interfaz de matriz que puede usar para crear un campo de bits.

Si su campo de bits es corto, probablemente pueda usar el módulo de estructura . De lo contrario, recomendaría algún tipo de envoltorio alrededor del el módulo de matriz .

Además, el módulo ctypes contiene bitfields , pero nunca lo he usado yo mismo. Caveat emptor .

Si desea utilizar ints (o ints largos) para representar como matrices de bools (o como conjuntos de enteros), eche un vistazo a http://sourceforge.net/projects/pybitop/files/

Proporciona inserción / extracción de campos de bits en entradas largas; encontrar el bit '1' más significativo o menos significativo; contando todos los 1's; inversión de bits; cosas como esa que es posible en Python puro pero mucho más rápido en C.

Para bits en su mayoría consecutivos, está el https://pypi.org/project/range_set/ módulo que es API compatible con la función integrada de Python set. Como su nombre lo indica, almacena los bits como pares de inicio / fin.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top