2008-09-27 29 views
39

Necesito una representación compacta de una matriz de booleanos, Python tiene un tipo de campo de bit integrado o ¿necesitaré encontrar una solución alternativa?¿Tiene Python un tipo de campo de bit?

+0

Para los casos en los que el término es ambiguo, supongo que quiere el tipo de características disponibles en los campos de bits C, o como se describe aquí? http://en.wikipedia.org/wiki/Bit_field – nealmcb

Respuesta

26

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 que una matriz booleana numpy, que parece usar un byte por elemento).

+0

¿Está 'BitArray' disponible para instalar en Windows? – IAbstract

+0

Parece que 'BitArray' está disponible para su instalación en Linux, pero nada en la página sugiere una instalación PIP para Windows. Bummer ... – IAbstract

4

NumPy tiene un módulo array interface que puede usar para crear un campo de bits.

+0

El módulo [matriz] incorporado (http://docs.python.org/library/array.html) también es suficiente para una matriz de bits y más portable (a través de las implementaciones de Python) que NumPy. – gsnedders

2

Si su bitfield es corto, probablemente pueda usar the struct module. De lo contrario, recomendaría una especie de envoltorio alrededor del the array module.

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

+1

Pero parece que el módulo struct representa cada bit como un carácter o byte, por lo que realmente no maneja los campos de bits como normalmente se define (donde los bits se empaquetan juntos en la memoria). – nealmcb

6

¡Utilizo los operadores de bits binarios!, &, |, ^, >> y < <. Funcionan muy bien y se implementan directamente en la C subyacente, que generalmente está directamente en el hardware subyacente.

6

representar cada uno de sus valores como una potencia de dos:

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

A continuación, para establecer un valor verdadero:

table = table | testB 

Para establecer un valor falso:

table = table & (~testC) 

Para prueba por 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).

+0

Gran respuesta. Me gusta y me desagrada que sea manual al mismo tiempo. Sin embargo, no hay una forma más lógica de construir manualmente una clase bitfield. – RobotHumans

11

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 binarios, octales, hexadecimales, enteros (grande o pequeño 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 analizar y modificarlas con funciones simples o notación rebanada - no hay 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 hay un concepto de una posición de bit, por lo que se puede tratarlo como un archivo o secuencia si eso es útil para usted. 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, dispondrá de soporte para los operadores binarios estándar bit a bit, embalaje, desembalaje, 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.

+1

¡Me gusta ese! Un poco más intuitivo que bitarray para mí. ¡Gracias! – weronika

+0

el enlace está muerto –

1

Si desea utilizar enteros (o enteros largos) para representar como matrices de Bools (o como conjuntos de números enteros), echar un vistazo a http://sourceforge.net/projects/pybitop/files/

Proporciona inserción/extracto de campos de bits en enteros largos; encontrar el '1' bit más significativo o menos significativo; contando todos los 1's; inversión de bits; cosas como esa, que son todas posibles en python puro, pero mucho más rápido en C.

29

Si desea principalmente 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 funciones estándar de Estructura y Unión de ctypes, como se describe en How Do I Properly Declare a ctype Structure + Union in Python? - Stack Overflow

Por ejemplo, para trabajar con los 4 bits menos significativos de un byte individualmente , simplemente nómbrelos de menos a más significativos en 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 lo que se hace 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í empezando por la más significativa, lo que parece más natural cuando se imprime) son 1, 1, 0, 0, es decir, 0xc en binario.

Cuestiones relacionadas