Python bitand (&) 与 and 的区别
大家好,我有一段代码:
for line in response.body.split("\n"):
if line != "":
opg = int(line.split(" ")[2])
opc = int(line.split(" ")[3])
value = int(line.split(" ")[5])
if opg==160 & opc==129:
ret['success'] = "valore: %s" % (value)
self.write(tornado.escape.json_encode(ret))
我有一系列的行,类型是
1362581670 2459546910990453036 156 0 30 0
我想要提取出只有第三个和第四个元素分别是160和129的那一行。可是这段代码不管用。我需要做一些类型转换吗?我觉得opg==160这个比较是没问题的,因为它是比较整数和整数……
3 个回答
2
&
是一种位运算。你可能想用的是 and
。在处理整数时,你可能不会觉得这有什么区别。
>>> True & False
False
>>> True & True
True
>>> False & False
False
但是,要注意 &
和 and
的 优先级是不同的。
>>> opc,opg = 160,129
>>> opc == 160 & opg == 129
False
>>> opc == 160 and opg == 129
True
简单来说,&
的优先级比 ==
高,所以 a == b & c == d
会被解析为 a == ( b & c) == d
,而不是你想要的 (a == b) & (c == d)
。
>>> def func1():
... opc,opg = 160,129
... opc == 160 & opg == 129
...
>>> def func2():
... opc,opg = 160,129
... opc == 160 and opg == 129
...
>>> import dis
>>> dis.dis(func1)
2 0 LOAD_CONST 3 ((160, 129))
3 UNPACK_SEQUENCE 2
6 STORE_FAST 0 (opc)
9 STORE_FAST 1 (opg)
3 12 LOAD_FAST 0 (opc)
15 LOAD_CONST 1 (160)
18 LOAD_FAST 1 (opg)
21 BINARY_AND
22 DUP_TOP
23 ROT_THREE
24 COMPARE_OP 2 (==)
27 JUMP_IF_FALSE_OR_POP 39
30 LOAD_CONST 2 (129)
33 COMPARE_OP 2 (==)
36 JUMP_FORWARD 2 (to 41)
>> 39 ROT_TWO
40 POP_TOP
>> 41 POP_TOP
42 LOAD_CONST 0 (None)
45 RETURN_VALUE
>>> dis.dis(func2)
2 0 LOAD_CONST 3 ((160, 129))
3 UNPACK_SEQUENCE 2
6 STORE_FAST 0 (opc)
9 STORE_FAST 1 (opg)
3 12 LOAD_FAST 0 (opc)
15 LOAD_CONST 1 (160)
18 COMPARE_OP 2 (==)
21 JUMP_IF_FALSE_OR_POP 33
24 LOAD_FAST 1 (opg)
27 LOAD_CONST 2 (129)
30 COMPARE_OP 2 (==)
>> 33 POP_TOP
34 LOAD_CONST 0 (None)
37 RETURN_VALUE
正如 Hoopdady 指出的那样,你在分割字符串时也做得不对。使用 line.split()
或 line.split(None)
可以在连续的空白字符上进行分割。
2
只需要用 line.split()
,而不是 line.split(" ")
。这样的话,它会处理任何类型的空白字符。如果不是单纯的空格,你可能会得到一些奇怪的结果,这可能就是你遇到的问题。
6
你可能对运算符搞混了;and
是正确的布尔测试,而 &
是一个二进制位运算符。
if opg == 160 and opc == 129:
作为一个数字运算符,&
的优先级比比较运算符高,而布尔运算符的优先级则较低。因此,表达式 opg == 160 & opc == 129
实际上会被解释为 opg == (160 & opc) == 129
,这可能不是你想要的结果。
你可以稍微简化一下你的代码:
for line in response.body.splitlines():
if line:
line = map(int, line.split())
opg, opc, value = line[2], line[3], line[5]
if opg == 160 and opc == 129:
ret['success'] = "valore: %s" % (value)
self.write(tornado.escape.json_encode(ret))