Разблокирует ли один бит флагов с помощью целых чисел переменной длины Python?
В моей программе (написанной на Python 3.4) у меня есть переменная, которая содержит различные флаги, например:
FLAG_ONE = 0b1
FLAG_TWO = 0b10
FLAG_THREE = 0b100
status = FLAG_ONE | FLAG_TWO | FLAG_THREE
Установка другого флага может быть легко выполнена с помощью
status |= FLAG_FOUR
Но что, если я явно хочу очистить флаг? Я бы сделал
status &= ~FLAG_THREE
Безопасен ли этот подход? Поскольку размер целого числа в Python не определен, что делать, если status
и FLAG_THREE
отличаются по размеру?
(status
должно быть поле бит, потому что мне нужно это значение для аппаратного протокола.)
Ответы
Ответ 1
Вы должны быть в безопасности, используя этот подход, да.
~
в Python просто реализуется как -(x+1)
(см. источник CPython), а отрицательные числа обрабатываются так, как будто они имеет любое требуемое количество 1s, заполняющее начало. Из Python Wiki:
Конечно, Python не использует 8-битные числа. Он ИСПОЛЬЗУЕТСЯ использовать, однако, многие биты были родными для вашей машины, но поскольку он был не переносимым, он недавно переключился на использование количества бит INFINITE. Таким образом, число -5 обрабатывается побитовыми операторами, как если бы оно было написано "... 1111111111111111111011".
Другими словами, с побитовым и &
вам гарантировано, что эти 1s будут заполнять длину ~FLAG
(отрицательное целое число) до длины status
. Например:
100000010000 # status
& ~10000 # ~FLAG
рассматривается как
100000010000
& 111111101111
= 100000000000 # new status
Это поведение описано в комментарии в источнике здесь.
Ответ 2
Удаление флага выполняется с помощью
status &= ~FLAG_THREE
потому что Python обрабатывает эти отрицательные значения как отрицательные:
>>> ~1L
-2L
>>> ~1
-2
>>> ~2
-3
Таким образом, оператор &
может действовать соответствующим образом и выводить желаемый результат независимо от длины операндов, поэтому 0b11111111111111111111111111111111111111111111111111111111111 & ~1
работает нормально, хотя левый операнд отличается от правого.
В другом направлении (RH длиннее LH), тем не менее, он работает, поскольку наличие избыточного количества битов 1
не имеет значения.