Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
B

bitarray

> 编程语言
Open source

efficient arrays of booleans for Python

792 stars0 likes1 views
WebsiteGitHub

About

efficient arrays of booleans for Python

bitarray: efficient arrays of booleans

This library provides an object type which efficiently represents an array of booleans. Bitarrays are sequence types and behave very much like usual lists. Eight bits are represented by one byte in a contiguous block of memory. The user can select between two representations: little-endian and big-endian. All functionality is implemented in C. Methods for accessing the machine representation are provided, including the ability to import and export buffers. This allows creating bitarrays that are mapped to other objects, including memory-mapped files.

Key features

  • The bit-endianness can be specified for each bitarray object, see below.

  • Sequence methods: slicing (including slice assignment and deletion), operations +, *, +=, *=, the in operator, len()

  • Bitwise operations: ~, &, |, ^, > (as well as their in-place versions &=, |=, ^=, >=).

  • Free-threading support (for GIL-disabled CPython 3.14 and later)

  • Fast methods for encoding and decoding variable-length prefix codes.

  • Bitarray objects support the buffer protocol (both importing and exporting buffers).

  • Efficient packing and unpacking for interoperability with byte-oriented objects such as NumPy arrays.

  • Pickling and unpickling of bitarray objects.

  • Immutable frozenbitarray objects which are hashable

  • Fast searching for bits and bit patterns

  • Type hinting

  • Extensive test suite with over 600 unit tests

  • Utility module bitarray.util:

    • conversion to and from hexadecimal strings
    • generating random bitarrays
    • pretty printing
    • conversion to and from integers
    • creating Huffman codes
    • compression of sparse bitarrays
    • run-length encoding
    • serialization and deserialization
    • various count functions
    • other helpful functions

Installation

Python wheels are are available on PyPI for all major platforms and Python versions. Which means you can simply:

.. code-block:: shell-session

$ pip install bitarray

Once you have installed the package, you may want to test it:

.. code-block:: shell-session

$ python -c 'import bitarray; bitarray.test()'
bitarray is installed in: /Users/ilan/bitarray/bitarray
sys.prefix: /Users/ilan/miniforge
bitarray version: 3.11.0
sys.version: 3.14.5 (main, May 20 2026) [Clang 20.1.8]
sys.abiflags: ''
sys._is_gil_enabled(): True
pointer size: 64 bit
sizeof(size_t): 8
sizeof(bitarrayobject): 80
HAVE_BUILTIN_BSWAP64: 1
default bit-endianness: big
machine byte-order: little
Py_GIL_DISABLED: 0
Py_DEBUG: 0
DEBUG: 0
.....................................s...................................
..........s.....................................s........................
......s.........................................................
----------------------------------------------------------------------
Ran 654 tests in 0.192s

OK (skipped=4)

The test() function is part of the API. It will return a unittest.runner.TextTestResult object, such that one can verify that all tests ran successfully by:

.. code-block:: python

import bitarray
assert bitarray.test().wasSuccessful()

Usage

As mentioned above, bitarray objects behave very much like lists, so there is not too much to learn. The biggest difference from list objects (except that bitarray are obviously homogeneous) is the ability to access the machine representation of the object. When doing so, the bit-endianness is of importance; this issue is explained in detail in the section below. Here, we demonstrate the basic usage of bitarray objects:

.. code-block:: python

>>> from bitarray import bitarray
>>> a = bitarray()         # create empty bitarray
>>> a.append(1)
>>> a.extend([1, 0])
>>> a
bitarray('110')
>>> x = bitarray(2 ** 20)  # bitarray of length 1048576 (initialized to 0)
>>> len(x)
1048576
>>> bitarray('1001 011')   # initialize from string (whitespace is ignored)
bitarray('1001011')
>>> lst = [1, 0, False, True, True]
>>> a = bitarray(lst)      # initialize from iterable
>>> a
bitarray('10011')
>>> a[2]    # indexing a single item will always return an integer
0
>>> a[2:4]  # whereas indexing a slice will always return a bitarray
bitarray('01')
>>> a[2:3]  # even when the slice length is just one
bitarray('0')
>>> a.count(1)
3
>>> a.remove(0)            # removes first occurrence of 0
>>> a
bitarray('1011')

Like lists, bitarray objects support slice assignment and deletion:

.. code-block:: python

>>> a = bitarray(50)
>>> a.setall(0)            # set all elements in a to 0
>>> a[11:37:3] = 9 * bitarray('1')
>>> a
bitarray('00000000000100100100100100100100100100000000000000')
>>> del a[12::3]
>>> a
bitarray('0000000000010101010101010101000000000')
>>> a[-6:] = bitarray('10011')
>>> a
bitarray('000000000001010101010101010100010011')
>>> a += bitarray('000111')
>>> a[9:]
bitarray('001010101010101010100010011000111')

In addition, slices can be assigned to booleans, which is easier (and faster) than assigning to a bitarray in which all values are the same:

.. code-block:: python

>>> a = 20 * bitarray('0')
>>> a[1:15:3] = True
>>> a
bitarray('01001001001001000000')

This is easier and faster than:

.. code-block:: python

>>> a = 20 * bitarray('0')
>>> a[1:15:3] = 5 * bitarray('1')
>>> a
bitarray('01001001001001000000')

Note that in the latter we have to create a temporary bitarray whose length must be known or calculated. Another example of assigning slices to Booleans, is setting ranges:

.. code-block:: python

>>> a = bitarray(30)
>>> a[:] = 0         # set all elements to 0 - equivalent to a.setall(0)
>>> a[10:25] = 1     # set elements in range(10, 25) to 1
>>> a
bitarray('000000000011111111111111100000')

As of bitarray version 2.8, indices may also be lists of arbitrary indices (like in NumPy), or bitarrays that are treated as masks, see Bitarray indexing __.

Bitwise operators

Bitarray objects support the bitwise operators ~, &, |, ^, > (as well as their in-place versions &=, |=, ^=, >=). The behavior is very much what one would expect:

.. code-block:: python

>>> a = bitarray('101110001')
>>> ~a  # invert
bitarray('010001110')
>>> b = bitarray('111001011')
>>> a ^ b  # bitwise XOR
bitarray('010111010')
>>> a &= b  # inplace AND
>>> a
bitarray('101000001')
>>> a >> a
bitarray('100000100')
>>> b >> 1  # return b right-shifted by 1
bitarray('011100101')

The C language does not specify the behavior of negative shifts and of left shifts larger or equal than the width of the promoted left operand. The exact behavior is compiler/machine specific. This Python bitarray library specifies the behavior as follows:

  • the length of the bitarray is never changed by any shift operation
  • blanks are filled by 0
  • negative shifts raise ValueError
  • shifts larger or equal to the length of the bitarray result in bitarrays with all values 0

It is worth noting that (regardless of bit-endianness) the bitarray left shift (>) always shifts towards higher indices.

Bit-endianness

For many purposes the bit-endianness is not of any relevance to the end user and can be regarded as an implementation detail of bitarray objects. However, there are use cases when the bit-endianness becomes important. These use cases involve explicitly reading and writing the bitarray buffer using .tobytes(), .frombytes(), .tofile() or .fromfile(), importing and exporting buffers. Also, a number of utility functions in bitarray.util will return different results depending on bit-endianness, such as ba2hex() or ba2int. To better understand this topic, please read bit-endianness __.

Buffer protocol

Bitarray objects support the buffer protocol. They can both export their own buffer, as well as import another object's buffer. To learn more about this topic, please read buffer protocol . There is also an example that shows how to memory-map a file to a bitarray: mmapped-file.py

Variable-length prefix codes

The .encode() method takes a dictionary mapping symbols to bitarrays and an iterable, and extends the bitarray object with the encoded symbols found while iterating. For example:

.. code-block:: python

>>> d = {'H':bitarray('111'), 'e':bitarray('0'),
...      'l':bitarray('110'), 'o':bitarray('10')}
...
>>> a = bitarray()
>>> a.encode(d, 'Hello')
>>> a
bitarray('111011011010')

Note that the string 'Hello' is an iterable, but the symbols are not limited to characters, in fact any immutable Python object can be a symbol. Taking the same dictionary, we can apply the .decode() method which will return an iterable of the symbols:

.. code-block:: python

>>> list(a.decode(d))
['H', 'e', 'l', 'l', 'o']
>>> ''.join(a.decode(d))
'Hello'

Symbols are not limited to being characters. The above dictionary d can be efficiently constructed using the function bitarray.util.huffman_code(). I also wrote Huffman coding in Python using bitarray __ for more background information.

When the codes are large, and you have many decode calls, most time will be spent creating the (same) internal decode tree objects. In this case, it will be much faster to create a decodetree object, which can be passed to bitarray's .decode() method, instead of passing the prefix code dictionary to those methods itself:

.. code-block:: python

>>> from bitarray import bitarray, decodetree
>>> t = decodetree({'a': bitarray('0'), 'b': bitarray('1')})
>>> a = bitarray('0110')
>>> list(a.decode(t))
['a', 'b', 'b', 'a']

The sole purpose of the immutable decodetree object is to be passed to bitarray's .decode() method.

Frozenbitarrays

A frozenbitarray object is very similar to the bitarray object. The difference is that this a frozenbitarray is immutable, and hashable, and can therefore be used as a dictionary key:

.. code-block:: python

>>> from bitarray import frozenbitarray
>>> key = frozenbitarray('1100011')
>>> {key: 'some value'}
{frozenbitarray('1100011'): 'some value'}
>>> key[3] = 1
Traceback (most recent call last):
    ...
TypeError: frozenbitarray is immutable

Reference

bitarray version: 3.11.0 -- change log __

In the following, item and value are usually a single bit - an integer 0 or 1.

Also, sub_bitarray refers to either a bitarray, or an item.

The bitarray object:

bitarray(initializer=0, /, endian='big', buffer=None) -> bitarray Return a new bitarray object whose items are bits initialized from the optional initializer, and bit-endianness. The initializer may be one of the following types: a.) int bitarray, initialized to zeros, of given length b.) bytes or bytearray to initialize buffer directly c.) str of 0s and 1s, ignoring whitespace and "_" d.) iterable of integers 0 or 1.

Optional keyword arguments:

endian: Specifies the bit-endianness of the created bitarray object. Allowed values are big and little (the default is big). The bit-endianness affects the buffer representation of the bitarray.

buffer: Any object which exposes a buffer. When provided, initializer cannot be present (or has to be None). The imported buffer may be read-only or writable, depending on the object type.

New in version 2.3: optional buffer argum

Issues· 7 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Python

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言