【问题标题】:Is there a builtin bitset that's similar to the std::bitset from C++?是否有类似于 C++ 中的 std::bitset 的内置位集?
【发布时间】:2023-03-28 09:26:01
【问题描述】:

我想在 Python 中使用一个位数组,我可以像 C++ 中的标准位集一样使用它。示例:

#include<bitset>
int main() {
    std::bitset<100> numBits;
}

不过不知道Python中是否有类似的东西,最好是内置的。

【问题讨论】:

  • 我猜你没有google it
  • @erip,这意味着python没有提供关于这个的内置工具?
  • @LightnessRacesinOrbit,抱歉,问题已更新,请帮忙。
  • 对不起,把问题改得有点过分了。
  • @jweyrich,感谢您的编辑。

标签: python bitset


【解决方案1】:

通常,您只需内置 int 类(或 python2 中的 long)。如果您特别关心隐藏班次,可以将其包装在一个类中。

【讨论】:

    【解决方案2】:

    没有任何内置的东西。如果您需要这样的数据结构来获得正确的字节输出,并设置正确的位,例如对于网络协议、二进制文件结构或硬件控制,将 True 和 False 值列表排序为字节很容易实现。

    还可以创建一个类以允许在字节数组对象中直接对内存中的位进行多次计算。但是,不太可能发生在 C++ 中,您不会获得速度或内存(好的,对于大型位集,您可以获得内存)优势 - Python 将处理每个位作为对 True 或 False 对象的完整引用(或完整的 0 和 1 整数),无论您在代码中做什么。

    也就是说,如果你有一个包含 True 和 False 值的列表,你想以位序列的形式输出到文件,例如,这样的代码可能会起作用:

    a = [True, True, False, False, False, True, ...]
    with open("myfile.bin", "wb" as file):
        for i, value in enumerate(a):
            if not i % 8:
                if i:
                    file.write(byte)
                byte = 0
            byte <<= 1
            byte |= value
         if i % 8:
            byte <<= (8 - i % 8)
            file.write(byte)
    

    一种更复杂的方法是为其创建全类支持,方法是将值保存在 bytearray 对象中,并在设置和重置操作时计算每个位索引 - 一种极简的方法是:

    class BitArray(object):
        def __init__(self, lenght):
            self.values = bytearray(b"\x00" * (lenght // 8 + (1 if lenght % 8  else 0)))
            self.lenght = lenght
    
        def __setitem__(self, index, value):
            value = int(bool(value)) << (7 - index % 8)
            mask = 0xff ^ (7 - index % 8)
            self.values[index // 8] &= mask
            self.values[index // 8] |= value
        def __getitem__(self, index):
            mask = 1 << (7 - index % 8)
            return bool(self.values[index // 8] & mask)
    
        def __len__(self):
            return self.lenght
    
        def __repr__(self):
            return "<{}>".format(", ".join("{:d}".format(value) for value in self))
    

    如您所见,这样做并没有提高速度,而且您需要大量位才能从中节省内存。这是在交互式提示中使用的上述类的示例:

    In [50]: a = BitArray(16)
    
    In [51]: a[0] = 1
    
    In [52]: a[15] = 1
    
    In [53]: a
    Out[53]: <1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>
    

    【讨论】:

      【解决方案3】:

      好吧,您可以使用布尔值列表创建一个“位集”:

      mybitset = [True, False, False, True, False]
      

      我缺乏上下文来给你一个更合适的回应。

      【讨论】:

      • 这可能取决于使用的python解释器。
      • sys.getsizeof(mybitset) 在我的机器上返回 104。将其视为指向单例的指针,因为每个 True 和 False 的 id 是相同的:&gt;&gt;&gt; [id(x) for x in mybitset] [139974218568224, 139974218568256, 139974218568256, 139974218568224, 139974218568256]
      【解决方案4】:

      你可以使用普通的list;但是,这在内存方面不是很有效:在 32 位 Python 构建上,每个“位”会浪费 4 个字节,而在 64 位构建上会浪费 8 个字节。这是因为列表的元素实际上是(引用)其他 Python 对象。

      Python 标准库也有内置的array 模块,它比通用的list 更有效地存储同质值,但不幸的是它不支持位作为数据类型。此外,它不提供Set 接口。

      因此,如果关注内存效率,那么您的选择可以归结为在 array 上构建自己的 Python 位集实现,或者从 PyPI 安装第 3 方模块,例如 intbitset

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-04
        相关资源
        最近更新 更多