是否使用Python可变长度整数在标志中取消了一个位?

时间:2016-01-18 13:20:59

标签: python bit-manipulation

在我的程序中(用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需要是一个位字段,因为我需要这个值用于硬件协议。)

2 个答案:

答案 0 :(得分:14)

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

Python中的

~简单地实现为-(x+1)(参见CPython source),负数被视为具有填充开头所需的任何数量的1。来自Python Wiki

  

当然,Python不使用8位数字。它用于使用但是许多位是你的机器本机的,但由于那是非便携式的,它最近已切换到使用INFINITE位数。因此,数字-5由按位运算符处理,就像它被写成" ... 1111111111111111111011"。

换句话说,使用按位和&,您可以保证这些1会将~FLAG(负整数)的长度填充到status的长度。例如:

  100000010000 # status
&       ~10000 # ~FLAG

被视为

  100000010000
& 111111101111

= 100000000000 # new status 

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

答案 1 :(得分:11)

清除标记适用于

status &= ~FLAG_THREE

因为Python将这些否定值视为否定:

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

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

在另一个方向(RH长于LH),它仍然可以工作,因为具有过多的1位并不重要。