Skip to content

Instantly share code, notes, and snippets.

@seblin
Last active October 2, 2018 14:39
Show Gist options
  • Save seblin/3f5d46855e1971b78319105c432614c9 to your computer and use it in GitHub Desktop.
Save seblin/3f5d46855e1971b78319105c432614c9 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
class Bits(object):
def __init__(self, value=0):
"""
Build a new Bits()-object based on the given value.
Examples:
Bits(0b1001)
Bits(42)
Bits('1001')
"""
self.int_value = value
@property
def int_value(self):
"""
Return integer representation of bits.
"""
return self._int_value
@int_value.setter
def int_value(self, value):
"""
Set value for bits which is converted to an integer.
"""
if isinstance(value, (str, bytes)):
self._int_value = int(value, base=2)
else:
self._int_value = int(value)
def __repr__(self):
"""
Return a representation of this object.
"""
return '{}({})'.format(type(self).__name__, bin(self))
def __str__(self):
"""
Return string representation of bits.
"""
return bin(self)
def __int__(self):
"""
Return the integer representation of bits.
"""
return self.int_value
def __index__(self):
"""
Similar to __int__(). Needed for bin(), hex(), oct().
"""
return int(self)
def __bool__(self):
"""
Return True if at least one bit is set, otherwise False.
"""
return bool(int(self))
def __eq__(self, other):
"""
Return True if bits are equal to other, otherwise False.
"""
return int(self) == int(other)
def __len__(self):
"""
Get the position of the highest bit being set.
"""
return int(self).bit_length()
def __getitem__(self, index):
"""
Get the n-th bit via index access.
Example:
Bits(0b1001)[2]
"""
if index < 0:
index += len(self)
if index < 0 or index >= len(self):
raise IndexError('index out of range')
return self.get_bit(index)
def __lshift__(self, other):
"""
Do bitwise left shift with other.
Example:
Bits(0b1001) << 3
"""
return self._do_op(int.__lshift__, other)
def __rshift__(self, other):
"""
Do bitwise right shift with other.
Example:
Bits(0b1001) >> 3
"""
return self._do_op(int.__rshift__, other)
def __and__(self, other):
"""
Do bitwise and with other.
Example:
Bits(0b1001) & Bits(0b1101)
"""
return self._do_op(int.__and__, other)
def __or__(self, other):
"""
Do bitwise or with other.
Example:
Bits(0b1001) | Bits(0b1101)
"""
return self._do_op(int.__or__, other)
def __xor__(self, other):
"""
Do bitwise exclusive or with other.
Example:
Bits(0b1001) ^ Bits(0b1101)
"""
return self._do_op(int.__xor__, other)
def __invert__(self):
"""
Invert the bits.
Example:
~Bits(0b1101)
"""
return self._do_op(int.__invert__)
def _do_op(self, op, other=None):
args = [int(self)]
if other is not None:
args.append(int(other))
return type(self)(op(*args))
def get_bit(self, n):
"""
Get the value of the n-th bit (0 or 1).
"""
return (int(self) >> n) & 1
def set_bit(self, n):
"""
Set the n-th bit to 1.
"""
return self | (1 << n)
def clear_bit(self, n):
"""
Set the n-th bit to 0.
"""
return self & ~(1 << n)
def toggle_bit(self, n):
"""
Switch the n-th bit to 0 or 1.
"""
return self ^ (1 << n)
def is_set(self, n):
"""
Return True if the n-th bit was set, otherwise False.
"""
return bool(self.get_bit(n))
@property
def values(self):
"""
Return a list representing the state of each bit.
"""
rng = range(len(self))
return [self.get_bit(n) for n in reversed(rng)]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment