Python中的and与or

从C语言家族,进入Python世界的程序员,当心都被Python中的andor骗了!

貌似正常

如果把Python当Java用,只使用bool类型来做逻辑运算,那么andor的表现都是正常的。

>>> 'yes' if True and False else 'no'
'no'
>>> True and False
False
>>> True or False
True

有些奇怪

但是,如果像C语言那样,把int也加进来玩,就有些奇怪了。

>>> 'yes' if True and 0 else 'no'
'no'
>>> True and 0
0
>>> True or 0
True

一会儿是0,一会儿是True。 Python不是动态强类型吗,怎么做bool运算得到了0

到底是怎么回事?

首先,要理解Python中的bool。 Python里没有Java那么严格的Boolean值检查,而是在需要bool类型时,用bool()去做转换。

C语言里,&&||的运算结果,是10; Java里,运算结果是truefalse。 在Python里,andor的运算结果,却不一定是TrueFalse

以下引自Python官方文档6.11. Boolean operations

The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.

The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.

也就是说,x and y,可以看做y if x else x; 而x or y,可以看做x if x else y

俺们如果按C语言家族的方式理解,就略有不同。 x and y,应该相当于bool(x) and bool(y)x or y,应该相当于bool(x) and bool(y)

这不知道是算Python的设计问题,还是文档问题。

按照它目前的设计,andor就不是什么逻辑运算符,而是值选择符

为什么这样设计

如果都是用来做逻辑判断,比如if x or y:,那么它和C语言家族的做法是等价的。 因为,bool(x or y),和bool(x) or bool(y),是等价的。

区别是,它少做了一次bool转换。

if x or y:来说,按照Python目前的做法, 相当于if bool(x if bool(x) else y):,只有两次bool转换。 而如果按照C语言家族的做法,则是if bool(bool(x) if bool(x) else bool(y))。 即使两个bool(x)可以通过编译器优化成一个,也仍然有三次bool转换。

每次基本的andor预算,都少一次bool转换,这优化着实不小。 也许,这就是为什么这么设计。

值选择符

既然如此,那么andor其实并非在做逻辑运算,而是在选择表达式的值。 一般or会用得多一些。

a = x or y or z

这一句表示,如果x非空非None,则给a赋值为x; 否则判断y,为空则赋值z。 从更抽象的角度来说,axyz三者中选取一个非空非None的值,优先级为x > y > z

它相当于:

a = x if x else y if y else z

or来表达,不仅更简洁,还更容易继续增长。

相对来说,and就不那么常用了。 毕竟,很少会优先挑选空值。

参考


相关笔记