Эффективные операции с битовыми массивами в PythonPython

Программы на Python
Anonymous
Эффективные операции с битовыми массивами в Python

Сообщение Anonymous »

Я реализую класс для обработки массивов битовых значений в Python. На данный момент вот что я сделал:

Код: Выделить всё

class Bitarray:
""" Representation of an array of bits.
:param bits: the list of boolean values (i.e. {False, True}) of the bitarray.
"""
def __init__(self, values:list[bool]):
self._bits:list[bool] = values
self._length:int = len(values)

@staticmethod
def from_bytes(data:bytes, byteorder:str = None):
def _access_bit(data, index):
""" Credits: https://stackoverflow.com/a/43787831/23022499
"""
base = int(index // 8)
shift = int(index % 8)
return (data[base] >> shift) & 0x1

if byteorder == None:
byteorder = sys.byteorder
elif byteorder != 'little' and byteorder != 'big':
raise ValueError('Param byteorder must be either "little" or "big".')

bin_data = [_access_bit(data, i) for i in range(len(data) * 8)]
bin_data = [bool(b) for b in bin_data]
return Bitarray(bin_data) if byteorder == 'big' else Bitarray(bin_data[::-1])

def __getitem__(self, index) -> bool:
return self._bits[index]

def __len__(self) -> int:
return self._length

# bit-wise operations
def __and__(self, other):
if type(other) != Bitarray:
raise TypeError("Unsupported operand type(s) for &: '{}' and '{}'".format(type(self), type(other)))

if self._length != len(other):
raise IndexError("The arguments for bitwise operations must have same length.")

return Bitarray([(a & b) for a, b in zip(self._bits, other._bits)])

def __or__(self, other):
if type(other) != Bitarray:
raise TypeError("Unsupported operand type(s) for &: '{}' and '{}'".format(type(self), type(other)))

if self._length != len(other):
raise IndexError("The arguments for bitwise operations must have same length.")

return Bitarray([(a | b) for a, b in zip(self._bits, other._bits)])

def __xor__(self, other):
if type(other) != Bitarray:
raise TypeError("Unsupported operand type(s) for &: '{}' and '{}'".format(type(self).__name__, type(other).__name__))

if self._length != len(other):
raise IndexError("The arguments for bitwise operations must have same length.")

return Bitarray([(a ^ b) for a, b in zip(self._bits, other._bits)])

# to string
def __str__(self):
return ''.join(str(int(b)) for b in self._bits)
Если вас интересует использование, я хочу сгенерировать случайные значения с помощью os.urandom(), а затем выполнить побитовые операции с этими значениями. Пример:

Код: Выделить всё

import os
import sys

a = Bitarray.from_bytes(os.urandom(16 // 8), sys.byteorder)
b = Bitarray.from_bytes(os.urandom(16 // 8), sys.byteorder)

print('XOR result: {}'.format(a ^ b))
Безусловно, то, что я сделал, работает. Но я почти уверен, что это настолько неэффективно, что для тех, кто читает это и знает о Python гораздо больше, я только что совершил какой-то ужасный грех. :P
Шутки в сторону, перебор логических значений для побитовых операций не может быть хорошим, не так ли? Есть ли более эффективный способ сделать это?
P.S. Для тех, кому интересно: я пытаюсь создать криптографический протокол, использующий случайные ключи и операции xor. Я знаю о некоторых модулях, таких как криптография, битовый массив и другие, но подумал, что было бы смешнее попытаться реализовать что-то самостоятельно. Извините за отсутствие документации и комментариев, я постараюсь улучшиться!
EDIT: Конечно, можно спросить, зачем мне использовать битовые массивы, если я мог бы просто выполнять побитовые операции, используя байты. Мне нужен доступ к однобитовым значениям, и я бы хотел, чтобы мой класс Bitarray мог выполнять побитовые операции без необходимости каждый раз возвращаться к байтам.

Подробнее здесь: https://stackoverflow.com/questions/784 ... -in-python

Вернуться в «Python»