Я вижу, вы получили отличные ответы в духе "манипуляции с битами". Однако, если вам придется многое сделать, я бы по-прежнему рекомендовал прочитать обсуждение здесь и ссылки на него, и, как предполагает эта вики, несколько пакетов, найденных таким образом (BitVector, BitPacket, bitarray) - удобочитаемость важна, и опыт показывает, что удаление неочевидного встроенного кода из потока на уровне приложения в пользу обращений к хорошо названным API-интерфейсам улучшает его.
Если вы решите пойти с манипуляциями, автоматическая генерация масок битовых диапазонов с учетом битовых индексов, безусловно, имеет решающее значение. Я бы порекомендовал начать с «атомарной битовой маски» с одним битом, построенным путем сдвига:
>>> bin(1 << 7)
'0b10000000'
как видите, 1 << 7
имеет единицу, за которой следуют 7 нулей - и, следовательно,
>>> bin((1 << 7) - 1)
'0b1111111'
(1 << 7) - 1
имеет ровно 7 единиц (вам нужны круглые скобки, потому что приоритет оператора сдвига <<
ниже, чем у оператора вычитания -
) в качестве младших значащих битов, иначе говоря, LSB (и, конечно, всех нулей) осталось от этого).
Учитывая простой способ сделать "битовую маску с N единицами" (как LSB), сделать единицы с битами N, включенными в набор исключенных M, и все другие очищенные, легко - используя именованные функции для дополнительной читаемости:
>>> def n_lsb(x): return (1 << x) - 1
...
>>> def n_to_m(n, m): return n_lsb(n) & ~ n_lsb(m)
...
>>> bin(n_to_m(7, 3))
'0b1111000'
Итак, теперь, чтобы установить биты N, включенные в M, исключенные по определенной схеме, как показали другие ответы:
>>> def set_bits(i, n, m, pat): return (i & ~n_to_m(n, m))|(pat<<m)
...
>>> bin(set_bits(511, 7, 3, 0b0101))
'0b110101111'
Хотя этот ответ сам по себе не позволяет вам делать что-то большее, чем другие, я надеюсь, что он поможет «научить вас ловить рыбу» (вместо того, чтобы просто дать вам рыбу ;-) и тем самым помочь вам ( и другие читатели) в будущем.
Кстати, я бы рекомендовал свести к минимуму сочетание битовых и арифметических операций - в этой А единственная арифметическая операция, которую я использую, заключается в том, что - 1
в n_lsb
, надеюсь, очень ясный случай; в более общих случаях арифметика с двумя дополнениями (как выглядит обычная целочисленная арифметика при взгляде с побитовой точки зрения) может быть хитрой.