在我的程序中(用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中整数的大小,如果status
和FLAG_THREE
的大小不同,该怎么办?
(status
需要是一个位字段,因为我需要这个值用于硬件协议。)
答案 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
位并不重要。