Package: bitint
bit-intPure 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 simpleintextension 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 ownsettype 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 greatnamedtuplefrom python standard library.Installationpip install bit-intor pipenvpipenv install -e 'git+https://github.com/czervenka/bit-set.git#egg=bitint'Usage>>> from bitint import bitintBitInt 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
1Similarlydoglabel represents the second bit, which has value2**1 = 2>>> Animals.dog
2We 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 ofpetsis0 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 useinoperator:>>> Animals.dog in pets
TrueWhat 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 bysetandunset>>> 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)
11000011Furthermore you can also create list of or iterate over names of set bits>>> list(pets)
['cat', 'dog']
>>> for pet in pets:
...     print(pet)
cat
dogor for instance create regular Python set>>> set(pets) == {'cat', 'dog'}
TrueBeside 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']TestingTests are documentation and vice-versa:python -m doctest bitint.py README.md