我需要一个布尔数组的紧凑表示,Python有内置的位域类型还是我需要找到一个替代解决方案?
如果您主要希望能够命名您的位字段并轻松操作它们,例如使用通信协议中表示为单个位的标志,那么您可以使用ctypes的标准结构和联合功能,如我所述在Python中正确声明一个ctype结构+联盟?- 堆栈溢出
例如,要单独处理一个字节的4个最低有效位,只需在LittleEndianStructure中将它们命名为最小到最重要.您使用联合提供对字节或int的相同数据的访问,以便您可以将数据移入或移出通信协议.在这种情况下,通过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)
这四个位(我在这里打印的最重要的,打印时看起来更自然)是1,1,0,0,即二进制的0xc.
当我最近有类似的需求时,Bitarray是我找到的最佳答案.它是一个C扩展(比BitVector快得多,它是纯python)并将其数据存储在一个实际的位域中(所以它的内存效率是一个numpy布尔数组的八倍,它似乎每个元素使用一个字节.)
您应该看看bitstring模块,它最近已达到2.0版本.二进制数据紧凑地存储为字节数组,可以轻松创建,修改和分析.
您可以BitString
从二进制,八进制,十六进制,整数(大或小端),字符串,字节,浮点数,文件等创建对象.
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
此外,还支持标准的逐位二进制运算符,打包,解包,字节序等.最新版本适用于Python 2.7和3.x,虽然它是纯Python,但它在内存和速度方面进行了相当好的优化.
我使用二进制逐位运算符!,&,|,^,>>和<<.它们工作得非常好,并且直接在底层C中实现,它通常直接在底层硬件上实现.
将您的每个值表示为2的幂:
testA = 2**0 testB = 2**1 testC = 2**3
然后设置值true:
table = table | testB
要设置值false:
table = table & (~testC)
要测试一个值:
bitfield_length = 0xff if ((table & testB & bitfield_length) != 0): print "Field B set"
如果这对您没有意义,请深入挖掘十六进制表示.这基本上是你如何跟踪嵌入式C应用程序中的布尔标志(如果你有限制内存).
BitVector包可能就是您所需要的.它不是内置于我的python安装中,但很容易在python站点上进行跟踪.
当前版本的https://pypi.python.org/pypi/BitVector.