title in python plot
¿Python tiene un tipo de campo de bit? (9)
¡Utilizo los operadores binarios de bits!, &, |, ^, >> y <<. Funcionan muy bien y se implementan directamente en la C subyacente, que generalmente está directamente en el hardware subyacente.
Necesito una representación compacta de una matriz de booleanos, ¿tiene Python un tipo de campo de bit integrado o tendré que encontrar una solución alternativa?
Debería echarle un vistazo al módulo de 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
partir de binarios, octal, hexadecimal, enteros (big o little endian), 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 segmentada, sin necesidad de 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 existe un concepto de posición de bit, por lo que puede tratarlo como un archivo o secuencia, si eso le resulta útil. Las propiedades se utilizan para dar diferentes interpretaciones de los datos de bit.
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 bit-wise, empaque, desempaquetado, endianness y más. La última versión es para Python 2.7 y 3.x, y aunque es pura Python, está razonablemente bien optimizada en términos de memoria y velocidad.
El paquete BitVector puede ser lo que necesita. No está integrado en mi instalación de Python, pero es fácil de localizar en el sitio de Python.
https://pypi.python.org/pypi/BitVector para la versión actual.
NumPy tiene un módulo de interfaz de matriz que puede usar para crear un campo de bits.
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"
Profundiza un poco más en la representación hexadecimal si esto no tiene sentido para ti. Esta es básicamente la forma en que realiza un seguimiento de sus indicadores booleanos en una aplicación C incrustada también (si tiene memoria limitada).
Si desea usar ints (o long ints) 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 bitfields en long ints; encontrar el ''1'' bit más significativo o menos significativo; contando todos los 1''s; inversión de bits; cosas así que todo es posible en python puro, pero mucho más rápido en C.
Si lo que desea es principalmente poder nombrar sus campos de bits y manipularlos fácilmente, por ejemplo, para trabajar con indicadores representados como bits individuales en un protocolo de comunicaciones, entonces puede usar las funciones estándar Estructura y Unión de ctypes , como se describe en ¿Cómo puedo hacer? ¿Declarar correctamente una Estructura tipo 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 menos a más significativos en una LittleEndianStructure. Utiliza una unión para proporcionar acceso a los mismos datos que un byte o int para poder mover los datos dentro o fuera del protocolo de comunicación. En este caso, eso se hace mediante el 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í empezando por el más significativo, que parece más natural al imprimir) son 1, 1, 0, 0, es decir, 0xc en binario.
Si su bitfield es corto, probablemente pueda usar el módulo struct . De lo contrario, recomendaría una especie de envoltorio alrededor del módulo de matriz .
Además, el módulo ctypes contiene bitfields , pero nunca lo he usado. Caveat Emptor .
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 pura python) 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).