Skip to main content

Pure Python implementation of extended integer with named bits.

Project description

bit-int

Pure Python implementation of extended integer with named bits.

I found that some Python engineers find working with bit math as sets unnatural. So I created this simple int extension to make bit manipulation more Pythonic and to demonstrate the beauty of Python magic.

What is BitInt good for in real life? It's as efficient as Python's own set type but it can be easily stored in databases, JSON or shared with other languages without any modification (C, Go, Java, JavaScript).

BitInt is highly inspired by great namedtuple from python standard library.

Installation

pip install bit-int

or pipenv

pipenv install -e 'git+https://github.com/czervenka/bit-set.git#egg=bitint'

Usage

>>> from bitint import bitint

BitInt is an integer type where bits can be named and manipulated as a set. Let's create a class Animals with first 8 bits named after animals kinds:

>>> Animals = bitint('Animals', 'cat, dog, mouse, bee, turtle, snake, frog, axolotl')

In this case, animals are represented by bits where cat is the first bit (2^0=1), dog is the second (2^1=2), mouse the third (2^2=4). You don't need to remember which animal is represented by which bit, because each species bit value is stored in property named after the species label:

>>> Animals.cat
1

Similarly dog label represents the second bit, which has value 2**1 = 2

>>> Animals.dog
2

We can now instantiate a subset of animals with set bits which corresponds to amphibians...

>>> amphibians = Animals('frog', 'axolotl')

... or animals which are commonly pets...

>>> pets = Animals('cat', 'dog')

Bit representation of pets is

0 0 0 0 0 0 1 1
            ^ ^
            | L cat (2^0 == 1 == Animals.cat)
            L dog (2^1 == 2 == Animals.dog)

Having this two sets of animals, we can use bit magic to test whether an animal bit is set to 1 or 0:

>>> "Dog is a pet" if Animals.dog & pets else "Dog is not a pet"
'Dog is a pet'

... or use in operator:

>>> Animals.dog in pets
True

What about if we try to check existence of an animal which has not been defined yet?

>>> Animals.elefant in pets
Traceback (most recent call last):
  ...
AttributeError: type object 'Animals' has no attribute 'elefant'

Beside checking for existense, it's possible to make basic set operations. For example, we can create a new Animals bitint which includes all pets and amphibians:

>>> pets | amphibians
Animals('cat', 'dog', 'frog', 'axolotl')

We can also find an intersection:

>>> hairy_animals = Animals('cat', 'dog', 'mouse')
>>> hairy_animals & pets
Animals('cat', 'dog')

... and even complement

>>> ~pets
Animals('mouse', 'bee', 'turtle', 'snake', 'frog', 'axolotl')

A set of all animals can be created using bit inversion of no animal

>>> all_animals = ~Animals()
>>> all_animals
Animals('cat', 'dog', 'mouse', 'bee', 'turtle', 'snake', 'frog', 'axolotl')

Animals can be added or removed from all animals by set and unset

>>> all_animals.unset(Animals.dog, Animals.bee, Animals.snake)
Animals('cat', 'mouse', 'turtle', 'frog', 'axolotl')

If you are curious which bits are set for named flags, print a bitint value.

>>> print(amphibians)
11000000
>>> print(pets | amphibians)
11000011

Furthermore you can also create list of or iterate over names of set bits

>>> list(pets)
['cat', 'dog']
>>> for pet in pets:
...     print(pet)
cat
dog

or for instance create regular Python set

>>> set(pets) == {'cat', 'dog'}
True

Beside everything else BitInt is just an enhanced integer :)

>>> pets + 1
4
>>> import json
>>> json.dumps({"pets_bitint": pets})
'{"pets_bitint": 3}'

Tip: If you change the named bits of a BitInt class (e.g. replace 'dog' with 'elephant') and you have stored bitints you need to make a migration otherwise all dogs become elephants. If you want to avoid migrations, never change existing named bit and only add new at the end of definition to utilize unused bits.

Update: My daughter found a bug in this readme:

>>> pets |= Animals.axolotl
>>> list(pets)
['cat', 'dog', 'axolotl']

Testing

Tests are documentation and vice-versa:

python -m doctest bitint.py README.md

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bitint-0.1.4.tar.gz (5.3 kB view details)

Uploaded Source

Built Distribution

bitint-0.1.4-py3-none-any.whl (6.0 kB view details)

Uploaded Python 3

File details

Details for the file bitint-0.1.4.tar.gz.

File metadata

  • Download URL: bitint-0.1.4.tar.gz
  • Upload date:
  • Size: 5.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for bitint-0.1.4.tar.gz
Algorithm Hash digest
SHA256 f10bb72c4372e6b9b275f3b2b5ffc919137c63703e575c69fc80910b6f787c4d
MD5 d47f0ffcdf4753f456dfc9fe33c00a1f
BLAKE2b-256 7471d52dc45bace50815d15bcb939c344515ad1c545ce65e8999c11f72387655

See more details on using hashes here.

File details

Details for the file bitint-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: bitint-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 6.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for bitint-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 cb35e766f0af13b5b5c0b6e3999e033f3ad50cf1b6cefd977c3a20c585469b88
MD5 7630f2318af241a94b722631e68a4d2f
BLAKE2b-256 7157616d2827ade1c47b7732dcfa1ed9595b85cab8877adc21e85e4f5aaf4181

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page