Python 相当于 Java 的 BitSet

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3946086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:04:54  来源:igfitidea点击:

Python equivalent to Java's BitSet

javapythonbitset

提问by Mantas Vidutis

Is there a Python class or module that implements a structure that is similar to the BitSet?

是否有实现类似于 BitSet 的结构的 Python 类或模块?

采纳答案by Glenn Maynard

There's nothing in the standard library. Try:

标准库中没有任何内容。尝试:

http://pypi.python.org/pypi/bitarray

http://pypi.python.org/pypi/bitarray

回答by Emil

Have a look at this implementationin Python 3.

看看Python 3中的这个实现

The implementation basically makes use of the built-in inttype, which is arbitrary precision integer type in Python 3 (where longis the Python 2 equivalent).

该实现基本上使用了内置int类型,它是 Python 3 中的任意精度整数类型(其中longPython 2 等效)。

#! /usr/bin/env python3

"""
bitset.py

Written by Geremy Condra

Licensed under GPLv3

Released 3 May 2009

This module provides a simple bitset implementation
for Python.
"""

from collections import Sequence
import math

class Bitset(Sequence):
    """A very simple bitset implementation for Python.

    Note that, like with normal numbers, the leftmost
    index is the MSB, and like normal sequences, that
    is 0.

    Usage:
        >>> b = Bitset(5)
        >>> b
        Bitset(101)
        >>> b[:]
        [True, False, True]
        >>> b[0] = False
        >>> b
        Bitset(001)
        >>> b << 1
        Bitset(010)
        >>> b >> 1
        Bitset(000)
        >>> b & 1
        Bitset(001)
        >>> b | 2
        Bitset(011)
        >>> b ^ 6
        Bitset(111)
        >>> ~b
        Bitset(110)
    """

    value = 0
    length = 0

    @classmethod
    def from_sequence(cls, seq):
        """Iterates over the sequence to produce a new Bitset.

        As in integers, the 0 position represents the LSB.
        """
        n = 0
        for index, value in enumerate(reversed(seq)):
            n += 2**index * bool(int(value))
        b = Bitset(n)
        return b

    def __init__(self, value=0, length=0):
        """Creates a Bitset with the given integer value."""
        self.value = value
        try: self.length = length or math.floor(math.log(value, 2)) + 1
        except Exception: self.length = 0

    def __and__(self, other):
        b = Bitset(self.value & int(other))
        b.length = max((self.length, b.length))
        return b

    def __or__(self, other):
        b = Bitset(self.value | int(other))
        b.length = max((self.length, b.length))
        return b

    def __invert__(self):
        b = Bitset(~self.value)
        b.length = max((self.length, b.length))
        return b

    def __xor__(self, value):
        b = Bitset(self.value ^ int(value))
        b.length = max((self.length, b.length))
        return b

    def __lshift__(self, value):
        b = Bitset(self.value << int(value))
        b.length = max((self.length, b.length))
        return b

    def __rshift__(self, value):
        b = Bitset(self.value >> int(value))
        b.length = max((self.length, b.length))
        return b

    def __eq__(self, other):
        try:
            return self.value == other.value
        except Exception:
            return self.value == other

    def __int__(self):
        return self.value

    def __str__(self):
        s = ""
        for i in self[:]:
            s += "1" if i else "0"
        return s

    def __repr__(self):
        return "Bitset(%s)" % str(self)

    def __getitem__(self, s):
        """Gets the specified position.

        Like normal integers, 0 represents the MSB.
        """
        try:
            start, stop, step = s.indices(len(self))
            results = []
            for position in range(start, stop, step):
                pos = len(self) - position - 1
                results.append(bool(self.value & (1 << pos)))
            return results
        except:
            pos = len(self) - s - 1
            return bool(self.value & (1 << pos))

    def __setitem__(self, s, value):
        """Sets the specified position/s to value.

        Like normal integers, 0 represents the MSB.
        """
        try:
            start, stop, step = s.indices(len(self))
            for position in range(start, stop, step):
                pos = len(self) - position - 1
                if value: self.value |= (1 << pos)
                else: self.value &= ~(1 << pos)
            maximum_position = max((start + 1, stop, len(self)))
            self.length = maximum_position
        except:
            pos = len(self) - s - 1
            if value: self.value |= (1 << pos)
            else: self.value &= ~(1 << pos)
            if len(self) < pos: self.length = pos
        return self

    def __iter__(self):
        """Iterates over the values in the bitset."""
        for i in self[:]:
            yield i

    def __len__(self):
        """Returns the length of the bitset."""
        return self.length

回答by Scott Griffiths

You might like to take a look at a module I wrote called bitstring(full documentation here), although for simple cases that need to be as fast as possible I'd still recommend bitarray.

您可能想看看我写的一个名为bitstring的模块(这里有完整的文档),尽管对于需要尽可能快的简单情况,我仍然推荐bitarray

Some similar questions:

一些类似的问题:

What is the best way to do Bit Field manipulation in Python?

在 Python 中进行位域操作的最佳方法是什么?

Does Python have a bitfield type?

Python 有位域类型吗?

Python Bitstream implementations

Python 比特流实现

回答by YvesgereY

I wouldn't recommend that in production code but for competitive programming, interview preparation and fun, one should make themselves familiar with bit fiddling.

我不建议在生产代码中使用它,但为了竞争性编程、面试准备和乐趣,人们应该让自己熟悉一些摆弄。

b = 0          # The empty bitset :)
b |= 1 << i    # Set
b & 1 << i     # Test
b &= ~(1 << i) # Reset
b ^= 1 << i    #?Flip i
b = ~b         # Flip all