Python bitand (&) 与 and 的区别

4 投票
3 回答
2702 浏览
提问于 2025-04-17 18:08

大家好,我有一段代码:

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))

撰写回答