Создать строку на основе битового поля

#python #bit-fields

#python #битовые поля

Вопрос:

Я использую 5-разрядное битовое поле для отслеживания состояния системы сигнализации в скрипте Python. Например, 0 в MSB означает «Не включен», в то время как 1 в MSB означает «Включен» и т.д. Это позволяет XOR в предыдущем состоянии и текущем состоянии быстро выдавать, какие биты были изменены:

 previous = 0b11001
current =  0b10011
delta = current ^ previous   # delta = 0b01010
  

Следующий шаг в моем коде — сгенерировать строку, описывающую, что изменилось, на основе delta . Существует 10 возможных состояний с описаниями. Мне интересно, как наилучшим образом создать эту строку. То, что у меня есть ниже, работает, но кажется неуклюжим:

 statusKey = {
         0: ' * Disarmed',
        10: ' * No Alarm',
        20: ' * No Fire',
        30: ' * No Check',
        40: ' * No AC',
         1: ' * Armed',
        11: ' * Alarm',
        21: ' * Fire',
        31: ' * Check',
        41: ' * AC'
         }

alert = ''
for i in range (5):
    if (0b10000 amp; (delta << i)):
         alert = ''.join((alert,statusKey[(10*i)   (0b01 amp; (current >> (4-i)))]))

#alert = 'No Alarm * Check'
  

Есть ли лучший способ структурировать данные в statusKey ?
И есть ли лучший способ сгенерировать alert строку на основе этой структуры?

Комментарии:

1. вы могли бы использовать numpy.bitwise_and поверх столбца, но это немного чрезмерно для такого количества данных. Ваш метод не ужасен.

2. @stevedc этот вопрос может лучше подойти для проверки кода , если вы хотите задать его там.

Ответ №1:

Старайтесь использовать как можно меньше побитовых математических операторов, потому что это делает ваш код очень нечитаемым. Простое понимание списка — это все, что вам действительно нужно. Кроме того, вы хотите, чтобы структура данных о вашем битовом статусе была самоописывающейся. Тот, кто читает это впервые, должен сразу понять логику.

 bit_status = {
    0: ("Disarmed", "Armed"),
    1: ("No Alarm", "Alarm"),
    2: ("No Fire", "Fire"),
    3: ("No Check", "Check"),
    4: ("No AC", "AC")
}

previous = 0b11001
current =  0b10011

current_bits = [current >> i amp; 1 for i in reversed(range(5))]
delta_bits = [(current ^ previous) >> i amp; 1 for i in reversed(range(5))]

status = [bit_status[index][current_bits[index]] 
    for index, delta_bit in enumerate(delta_bits) if delta_bit == 1]

print(" * ".join(status))
# No Alarm * Check