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中整数的大小,因此大小如何status且FLAG_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位数并不重要.