使用 Python 可变长度整数取消设置标志中的单个位是否安全?

Is unsetting a single bit in flags safe with Python variable-length integers?

在我的程序中(用 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中整数的大小没有定义,如果statusFLAG_THREE大小不同怎么办?

status 需要是一个位字段,因为我需要这个值用于硬件协议。)

清除标志适用于

status &= ~FLAG_THREE

因为 Python 将那些取反的值视为负值:

>>> ~1L
-2L
>>> ~1
-2
>>> ~2
-3

因此 & 运算符可以适当地执行操作并产生所需的结果,而不管操作数的长度如何,因此 0b11111111111111111111111111111111111111111111111111111111111 & ~1 可以正常工作,尽管左手操作数比右手操作数不同。

在另一个方向(RH 比 LH 长),它仍然有效,因为 1 位的数量过多并不重要。

你应该安全地使用这种方法,是的。

~ 在 Python 中简单地实现为 -(x+1)(参见 CPython source) and negative numbers are treated as if they have any required number of 1s padding the start. From the Python Wiki:

Of course, Python doesn't use 8-bit numbers. It USED to use however many bits were native to your machine, but since that was non-portable, it has recently switched to using an INFINITE number of bits. Thus the number -5 is treated by bitwise operators as if it were written "...1111111111111111111011".

换句话说,使用 bitwise-and & 可以保证这些 1 会将 ~FLAG(负整数)的长度填充到 [=16= 的长度].例如:

  100000010000 # status
&       ~10000 # ~FLAG

被视为

  100000010000
& 111111101111

= 100000000000 # new status 

来源 here 的评论中描述了此行为。