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

elz*_*ell 30 python bit-manipulation

在我的程序中(用Python 3.4编写)我有一个包含各种标志的变量,例如:

FLAG_ONE = 0b1
FLAG_TWO = 0b10
FLAG_THREE = 0b100
status = FLAG_ONE | FLAG_TWO | FLAG_THREE
Run Code Online (Sandbox Code Playgroud)

可以轻松地设置另一个标志

status |= FLAG_FOUR
Run Code Online (Sandbox Code Playgroud)

但是,如果我明确要清除旗帜呢?我会做

status &= ~FLAG_THREE
Run Code Online (Sandbox Code Playgroud)

这种方法安全吗?由于未定义Python中整数的大小,因此大小如何statusFLAG_THREE不同?

(status需要有点字段,因为我需要这个值用于硬件协议.)

Ale*_*ley 14

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

~在Python中简单地实现为-(x+1)(参见CPython源),并且将负数视为具有任何所需数量的1填充开头.来自Python Wiki:

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

换句话说,使用按位 - 并且&您可以保证那些1将填充~FLAG(负整数)的长度为长度status.例如:

  100000010000 # status
&       ~10000 # ~FLAG
Run Code Online (Sandbox Code Playgroud)

被视为

  100000010000
& 111111101111

= 100000000000 # new status 
Run Code Online (Sandbox Code Playgroud)

此处的源代码中的注释中描述了此行为.


glg*_*lgl 11

清除旗帜适用于

status &= ~FLAG_THREE
Run Code Online (Sandbox Code Playgroud)

因为Python将那些否定的值视为否定:

>>> ~1L
-2L
>>> ~1
-2
>>> ~2
-3
Run Code Online (Sandbox Code Playgroud)

因此,&操作者可以适当地行动并产生想要的结果,而不管操作数的长度如何,因此0b11111111111111111111111111111111111111111111111111111111111 & ~1尽管左手操作数比右手操作数更双,但是工作正常.

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