Вопрос

Мне нужно компактное представление массива логических значений, есть ли в Python встроенный тип битового поля или мне нужно будет найти альтернативное решение?

Это было полезно?

Решение

Битаррей это был лучший ответ, который я нашел, когда у меня недавно возникла аналогичная потребность.Это расширение C (намного быстрее, чем BitVector, который является чистым python) и хранит свои данные в реальном битовом поле (таким образом, это в восемь раз эффективнее памяти, чем логический массив numpy, который, по-видимому, использует байт на элемент.)

Другие советы

Если вы в основном хотите иметь возможность называть свои битовые поля и легко манипулировать ими, напримердля работы с флагами, представленными в виде отдельных битов в протоколе связи, вы можете использовать стандартную структуру и функции объединения типы данных, как описано в Как мне правильно объявить ctype Structure + Union в Python?- Переполнение стека

Например, чтобы работать с 4 младшими значащими битами байта по отдельности, просто назовите их от наименьшего до наиболее значимого в небольшой иерархической структуре.Вы используете объединение для предоставления доступа к тем же данным, что и байт или int, чтобы вы могли перемещать данные в протокол связи или из него.В данном случае это делается с помощью flags.asbyte поле:

import ctypes
c_uint8 = ctypes.c_uint8

class Flags_bits(ctypes.LittleEndianStructure):
    _fields_ = [
            ("logout", c_uint8, 1),
            ("userswitch", c_uint8, 1),
            ("suspend", c_uint8, 1),
            ("idle", c_uint8, 1),
        ]

class Flags(ctypes.Union):
    _fields_ = [("b", Flags_bits),
                ("asbyte", c_uint8)]

flags = Flags()
flags.asbyte = 0xc

print(flags.b.idle)
print(flags.b.suspend)
print(flags.b.userswitch)
print(flags.b.logout)

Четыре бита (которые я напечатал здесь, начиная с самого значимого, что кажется более естественным при печати) равны 1, 1, 0, 0, т.е.0xc в двоичном формате.

Вам следует взглянуть на битовая строка модуль, который недавно достиг версии 2.0.Двоичные данные компактно хранятся в виде массива байтов и могут быть легко созданы, изменены и проанализированы.

Вы можете создавать BitString объекты из двоичной, восьмеричной, шестнадцатеричной системы счисления, целых чисел (с большим или меньшим порядковым номером), строк, байтов, чисел с плавающей запятой, файлов и многого другого.

a = BitString('0xed44')
b = BitString('0b11010010')
c = BitString(int=100, length=14)
d = BitString('uintle:16=55, 0b110, 0o34')
e = BitString(bytes='hello')
f = pack('<2H, bin:3', 5, 17, '001') 

Затем вы можете анализировать и изменять их с помощью простых функций или нотации среза - не нужно беспокоиться о битовых масках и т.д.

a.prepend('0b110')
if '0b11' in b:
    c.reverse()
g = a.join([b, d, e])
g.replace('0b101', '0x3400ee1')
if g[14]:
    del g[14:17]
else:
    g[55:58] = 'uint:11=33, int:9=-1'

Существует также концепция битовой позиции, так что вы можете рассматривать ее как файл или поток, если это вам полезно.Свойства используются для предоставления различных интерпретаций битовых данных.

w = g.read(10).uint
x, y, z = g.readlist('int:4, int:4, hex:32')
if g.peek(8) == '0x00':
    g.pos += 10

Кроме того, есть поддержка стандартных побитовых двоичных операторов, упаковки, распаковки, порядкового номера и многого другого.Последняя версия предназначена для Python 2.7 и 3.x, и хотя это чистый Python, он достаточно хорошо оптимизирован с точки зрения памяти и скорости.

Я использую двоичные побитовые операторы !, &, |, ^, >>, и <<.Они работают действительно хорошо и реализованы непосредственно в базовом C, который обычно находится непосредственно на базовом оборудовании.

Представьте каждое из ваших значений в виде степени двойки:

testA = 2**0
testB = 2**1
testC = 2**3

Затем, чтобы установить значение true:

table = table | testB

Чтобы установить значение false:

table = table & (~testC)

Для проверки значения:

bitfield_length = 0xff
if ((table & testB & bitfield_length) != 0):
    print "Field B set"

Копните немного глубже в шестнадцатеричное представление, если это не имеет для вас смысла.По сути, именно так вы отслеживаете свои логические флаги и во встроенном приложении на языке Си (если у вас ограничена память).

Пакет BitVector может быть тем, что вам нужно.Он не встроен в мою установку python, но его легко найти на сайте python.

https://pypi.python.org/pypi/BitVector для текущей версии.

У NumPy есть интерфейс массива модуль, который вы можете использовать для создания битового поля.

Если ваше битовое поле короткое, вы, вероятно, можете использовать модуль struct ( структура).В противном случае я бы порекомендовал какую-нибудь обертку вокруг модуль массива.

Кроме того, модуль ctypes содержит битовые поля, но я сам никогда им не пользовался. Будьте внимательны.

Если вы хотите использовать целые числа (или длинные целые числа) для представления в виде массивов bools (или в виде наборов целых чисел), взгляните на http://sourceforge.net/projects/pybitop/files/

Он обеспечивает вставку / извлечение битовых полей в длинные целые числа;поиск наиболее значимого или наименее значимого бита "1";подсчет всех 1-х;реверсирование бита;подобные вещи, которые возможны в чистом python, но намного быстрее в C.

Для преимущественно последовательных битов существует https://pypi.org/project/range_set/ модуль, совместимый по API со встроенным в Python set.Как следует из названия, он хранит биты в виде пар начало / конец.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top