我需要一个布尔数组的紧凑表示,Python是否有内置的位域类型,还是需要找到替代解决方案?

有帮助吗?

解决方案

Bitarray 是我发现的最佳答案,当时我最近有类似的需求。它是一个C扩展(比BitVector快得多,它是纯python)并将其数据存储在一个实际的位域中(因此它的内存效率是一个numpy布尔数组的八倍,这似乎每个元素使用一个字节。)

其他提示

如果您主要希望能够为您的位字段命名并轻松操作它们,例如要使用在通信协议中表示为单个位的标志,那么您可以使用 ctypes ,如如何在Python中正确声明ctype结构+联合? - Stack Overflow

例如,要单独处理一个字节的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。

您应该查看 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,但在内存和速度方面进行了相当好的优化。

我使用二进制逐位运算符!,<!> amp;,|,^,<!> gt; <!> gt;和<!> lt; <!> lt;。它们工作得很好,直接在底层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 了解当前版本

NumPy有一个阵列接口模块,您可以使用它来制作位域。

如果您的位域很短,您可以使用结构模块 。否则,我建议在阵列模块周围使用某种包装。

此外,ctypes模块确实包含 bitfields ,但我自己从未使用过它。 警告经纪人

如果你想使用整数(或长整数)表示为bool数组(或整数组),请看一下 http://sourceforge.net/projects/pybitop/files/

它将位域的插入/提取提供为长整数;找到最重要或最不重要的'1'位;计算所有的1;位反向;像纯python一样可能的东西,但在C中更快。

对于大多数连续的位,有 https://pypi.org/project/range_set/与Python的内置set API兼容的模块。顾名思义,它将这些位存储为开始/结束对。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top