你会进一步发现这样两条规律:
- 如果一个条件为真,那么它 or 另一个条件无论真假,结果一定为真
- 如果一个条件为假,那么它 and 另一个条件无论真假,结果一定为假
于是,编程语言在此基础上建立了一种叫做「短路求值」的执行策略,即:
根据已知条件已经可以确定整个逻辑表达式的结果时,就不再计算剩余表达式的值。
Python也是如此。
比如这段代码:
代码语言:javascript复制x = 5
y = 10
if x > 0 or y < 15:
print('条件满足')
程序计算出 x > 0 为True之后,就不会再计算 y < 15的值,因为无论后面是True还是False,都不影响最终的结果。
为了证明这一点,我们把代码改写一下,把后一个表达式变成函数,并在其中加上一句输出以便观察:
代码语言:javascript复制x = -5
y = 10
def y小于(n):
print('y小于n吗?')
return y < n
if x > 0 or y小于(15):
print('条件满足')
输出:
代码语言:javascript复制条件满足
运行结果中没有输出函数中的print语句,可见函数没有被执行。
而如果把 x 变成 -5,则输出:
代码语言:javascript复制y小于n吗?
条件满足
说明函数被执行了。
短路求值的作用显而易见,就是避免执行不必要的代码,提高程序的效率。
我们在写代码的时候,也可以利用这一点简化代码。
比如要判断 b 是否为 a 的整数倍,如果只是这么写:
代码语言:javascript复制a = int(input())
b = 9
if b % a == 0:
print('b是a的整数倍')
那么当a为0时,就会抛出除0错误,因为整数不能除以0或者对0取模:
代码语言:javascript复制ZeroDivisionError: integer division or modulo by zero
而避免这种情况,不必多加一层if,只需要把现有条件增加一下,改为:
代码语言:javascript复制if a != 0 and b % a == 0:
这样当a为0时,条件直接短路返回False,不会再执行后面的取模运算。
此外,对于非bool值的逻辑运算,短路求值就不仅只是效率上的优化,更是直接决定了运算的结果。
当两个非bool值进行 and 运算时,如果前值转成bool值为False,就会触发 and 短路求值,运算的结果就是前值;
而如果前值转成bool值为True,不会触发短路求值,结果则是后值。
代码语言:javascript复制print(0 and 2)
print(3 and 1)
输出:
代码语言:javascript复制0
1
or运算也是类似,如果前值转成bool值为True,就会触发 or 短路求值,运算的结果就是前值;
而如果前值转成bool值为False,不会触发短路求值,结果则是后值。
代码语言:javascript复制print(2 or 1)
print(0 or 3)
输出:
代码语言:javascript复制2
3
短路求值对于多个连续的and或者多个连续的or也一样有效。
多个and的结果,会短路在第一个假值,否则为最后一个值;
多个or的结果,会短路在第一个真值,否则为最后一个值。
代码语言:javascript复制print(1 and [] and 0 and 2)
print(0 or 'a' or 3 or [])
输出:
代码语言:javascript复制[]
a
最后留一个思考题:
代码语言:javascript复制0 and 1 or 2 and 3 or 4 and 5
结果是多少?为什么?