Last active
October 2, 2018 14:39
-
-
Save seblin/3f5d46855e1971b78319105c432614c9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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