我的问题是这两句话:
> 2 == 2 == True
False
> (2 == 2) == True
True
我很困惑。我希望两个表达式是相同的,因为Python会从左到右计算表达式,所以:
# 2 == 2 == True
# | |
# ------
# |
# True == True
和
# (2 == 2) == True
# | |
# ------
# |
# True == True
即使我改变顺序(如果Python从右到左求值),我得到同样令人困惑的结果:
> True == 2 == 2
False
> True == (2 == 2)
True
有人能帮我一下吗?比较链。2 == 2 == True
被评估为2 == 2 and 2 == True
,第二次比较显然是假的。(2
可能为真,但True
不为真)
您可以使用ast
模块查看从每个表达式生成的不同抽象语法树(ast)。
>>> print(ast.dump(ast.parse("2 == 2 == True").body[0], indent=2))
Expr(
value=Compare(
left=Constant(value=2),
ops=[
Eq(),
Eq()],
comparators=[
Constant(value=2),
Constant(value=True)]))
>>> print(ast.dump(ast.parse("(2 == 2) == True").body[0], indent=2))
Expr(
value=Compare(
left=Compare(
left=Constant(value=2),
ops=[
Eq()],
comparators=[
Constant(value=2)]),
ops=[
Eq()],
comparators=[
Constant(value=True)]))
仅看AST并不能明显看出A op1 B op2 C
等同于A op1 B and B op2 C
(您可以看到,有一个单个Compare
表达式具有两个操作符和两个"比较器",而不是一个Compare
表达式具有单个操作符和另一个Compare
表达式作为一个操作数)。为此,您需要文档:
形式上,如果
a
、b
、c
、…、y
、z
是表达式,op1
、op2
、…、opN
是比较运算符,则a op1 b op2 c ... y opN z
等价于a op1 b and b op2 c and ... y opN z
,只是每个表达式最多求值一次。
AST提供信息,代码生成器提供该信息的语义。
>>> import dis
>>> dis.dis('2==2==True')
1 0 LOAD_CONST 0 (2)
2 LOAD_CONST 0 (2)
4 DUP_TOP
6 ROT_THREE
8 COMPARE_OP 2 (==)
10 JUMP_IF_FALSE_OR_POP 18
12 LOAD_CONST 1 (True)
14 COMPARE_OP 2 (==)
16 RETURN_VALUE
>> 18 ROT_TWO
20 POP_TOP
22 RETURN_VALUE
>>> dis.dis('(2==2)==True')
1 0 LOAD_CONST 0 (2)
2 LOAD_CONST 0 (2)
4 COMPARE_OP 2 (==)
6 LOAD_CONST 1 (True)
8 COMPARE_OP 2 (==)
10 RETURN_VALUE