问题
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