问题
Hi all I have this part of code:
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))
I have a series if line of type
1362581670 2459546910990453036 156 0 30 0
I want to take only the line where the third and fourth element are respectively 160 and 129. This code doesn't work. Do I have to do some casting? I think opg==160 is working to campare int with int...
回答1:
You got confused with the operators; and is the correct boolean test, & is a binary bitwise operator instead:
if opg == 160 and opc == 129:
As a numeric operator, the & operator has a higher precedence than comparison operators, while the boolean operators have a lower precedence. The expression opg == 160 & opc == 129 is thus interpreted as opg == (160 & opc) == 129 instead, which is probably not what you wanted.
You can simplify your code somewhat:
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))
回答2:
Just use line.split() instead of line.split(" "). That way it handles any type of whitespace. If those aren't just spaces, you'll get some weird results, which may be what's happening.
回答3:
& is a bitwise operation. You probably want and. With integers, you might not think that it would make a difference
>>> True & False
False
>>> True & True
True
>>> False & False
False
However, note that & and and have different priorities.
>>> opc,opg = 160,129
>>> opc == 160 & opg == 129
False
>>> opc == 160 and opg == 129
True
Basically, & binds tighter than ==, so a == b & c == d is parsed as a == ( b & c) == d rather than (a == b) & (c == d) like you wanted.
>>> 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
As pointed out by Hoopdady, you also aren't splitting your string correctly. line.split() or line.split(None) will split on consecutive runs of whitespace.
来源:https://stackoverflow.com/questions/15251121/python-bitand-vs-and