Лично я на практике встречал использование побитовых операторов в двух ситуациях (их конечно намного больше).
🔸1. Сдвиг, который соответствует некоторой математической операции (арифметический сдвиг) но работает несравнимо быстрей. Например сдвиг влево равен выражению a*2**b:
a<<b == a*2**b
А также определение знака числа или нахождение модуля без условного оператора, что также очень быстро делается. И другие операции.
🔸2. Числовые маски.
Что это такое?
Создаем несколько переменных, в которых в бинарном представлении все ячейки заполнены
нулями кроме одной позиции. И у каждой переменной используется своя уникальная позиция для бита 1.
FLAG1 = int('001', 2) # 2
FLAG2 = int('010', 2) # 4
FLAG3 = int('100', 2) # 8
Теперь с помощью оператора OR можем объединять все биты в одну маску
>>> flags = FLAG1 | FLAG2
3 # 011
А после проверить, входит ли определённый флаг в состав битов маски?
>>> flags & FLAG3
0 # 000 нет совпадений
>>> flags & FLAG2
2 # 010 совпал второй бит
Если результат больше 0 то флаг присутствует в маске. Если результат 0 то такого флага нет.
Чтобы получить тип bool можем писать так
bool(flags & FLAG2)
или так
flags & FLAG2 > 0
и, очевидно, так
if flags & FLAG1:
...
Где могут пригодиться такие маски? Один пример был в предыдущем посте про флаги в Qt фреймворке. Также такой способ часто используют в организации прав доступа к ресурсам.
READ = int('001', 2) # 2
WRITE = int('010', 2) # 4
DELETE = int('100', 2) # 8
USER = READ
MODERATOR = READ | WRITE
ADMIN = READ | WRITE | DELETE
can_write = ADMIN & WRITE
Не сложно представить альтернативу на простом Python
READ = 1
WRITE = 2
DELETE = 3
USER = [READ]
MODERATOR = [READ, WRITE]
ADMIN = [READ, WRITE, DELETE]
can_write = WRITE in ADMIN
Оператор in работает довольно шустро, но всё равно медленней чем побитовый оператор.
#tricks