python链式比较

Python中print('a' < 'b' < 'c')的运行结果是什么呢?

1552928102571

Part 1

本文来自一个奇怪的问题

print('a' < 'b' < 'c')的运行结果是什么?

答案是True

这段代码在Python2 和Python3上的运行结果是相同的,均为True.

1552928182146

Part 2

但是这是为啥呢?

直觉猜测这是按照运算优先级进行的运算,即:

1
2
3
print('a' < 'b' < 'c')
# 等同于
print(('a' < 'b') < 'c')

但这段代码在Python2和Python3中的运行结果是不同的:Python2运行结果仍为True. Python3中则运行出错,错误信息如下:

1
2
3
4
>>> print(('a'<'b')<'c')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: bool() < str()

从这里我们可以看出两点:

  • 我们的猜测是错误的,并非是顺序结合执行的
  • Python3对比较的要求更加严格,不会进行自动类型转换(\(bool \to str\))

实际测试确实如此,在逻辑比较运算中,数字和布尔值都不会自动转换为字符串来进行比较

Part3

那问题来了,上述的思路不行,那实际到底发生了啥呢?

经过谷歌搜索,我终于在官方文档中找到了相关说明:

if a, b, c, ..., y, z are expressions and opa, opb, ..., opy are comparison operators, then a opa b opb c ...y opy z is equivalent to a opa b and b opb c and ... y opy z, except that each expression is evaluated at most once.

这段话的意思就是

如果有一个比较如下 :

1
'a' < 'b' < 'c' < ...

它相当于:

1
'a' < 'b' and 'b' < 'c' and 'c' < ...

Final

至此问题终于得到了解决

'a' < 'b' < 'c' 被Python翻译为了 'a' < 'b' and 'b' < 'c'.

所以结果理所当然的为True喽!