Python支持短路运算吗?

457 投票
3 回答
151143 浏览
提问于 2025-04-15 21:15

Python支持布尔表达式中的短路运算吗?

3 个回答

63

好的。你可以在你的Python解释器里试试下面的内容:

>>>False and 3/0
False
>>>True and 3/0
ZeroDivisionError: integer division or modulo by zero

或者

>>>True or 3/0
True
>>>False or 3/0
ZeroDivisionError: integer division or modulo by zero
269

运算符 andor 的短路行为:

首先,我们定义一个有用的函数,用来判断某个操作是否被执行。这个简单的函数接受一个参数,打印一条消息,然后返回这个输入,内容不变。

>>> def fun(i):
...     print "executed"
...     return i
... 

我们可以在下面的例子中观察到 Python 的短路行为,特别是在 andor 运算符中:

>>> fun(1)
executed
1
>>> 1 or fun(1)    # due to short-circuiting  "executed" not printed
1
>>> 1 and fun(1)   # fun(1) called and "executed" printed 
executed
1
>>> 0 and fun(1)   # due to short-circuiting  "executed" not printed 
0

注意:以下值被解释器视为假:

        False    None    0    ""    ()    []     {}

函数 any()all() 的短路行为:

Python 的 any()all() 函数也支持短路行为。正如文档中所示,它们会按顺序检查序列中的每个元素,直到找到一个结果,可以提前结束评估。下面的例子可以帮助理解这两个函数。

any() 函数检查是否有任何元素为真。一旦遇到一个真值,它就会停止执行并返回真。

>>> any(fun(i) for i in [1, 2, 3, 4])   # bool(1) = True
executed
True
>>> any(fun(i) for i in [0, 2, 3, 4])   
executed                               # bool(0) = False
executed                               # bool(2) = True
True
>>> any(fun(i) for i in [0, 0, 3, 4])
executed
executed
executed
True

all() 函数检查所有元素是否都为真,一旦遇到一个假值,它就会停止执行:

>>> all(fun(i) for i in [0, 0, 3, 4])
executed
False
>>> all(fun(i) for i in [1, 0, 3, 4])
executed
executed
False

链式比较的短路行为:

此外,在 Python 中

比较可以任意链式连接;例如,x < y <= z 等同于 x < y and y <= z,但在这种情况下,y 只会被评估一次(不过在 x < y 为假时,z 根本不会被评估)。

>>> 5 > 6 > fun(3)    # same as:  5 > 6 and 6 > fun(3)
False                 # 5 > 6 is False so fun() not called and "executed" NOT printed
>>> 5 < 6 > fun(3)    # 5 < 6 is True 
executed              # fun(3) called and "executed" printed
True
>>> 4 <= 6 > fun(7)   # 4 <= 6 is True  
executed              # fun(3) called and "executed" printed
False
>>> 5 < fun(6) < 3    # only prints "executed" once
executed
False
>>> 5 < fun(6) and fun(6) < 3 # prints "executed" twice, because the second part executes it again
executed
executed
False

编辑:
还有一个有趣的点Python 中的逻辑 andor 运算符返回的是操作数的,而不是布尔值(TrueFalse)。例如:

操作 x and y 的结果是 如果 x 为假,则返回 x,否则返回 y

这与其他语言不同,例如 C 语言中的 &&|| 运算符返回的是 0 或 1。

例子:

>>> 3 and 5    # Second operand evaluated and returned 
5                   
>>> 3  and ()
()
>>> () and 5   # Second operand NOT evaluated as first operand () is  false
()             # so first operand returned 

同样,or 运算符返回的是最左边的值,只要 bool(value)True,否则返回最右边的假值(根据短路行为),例子如下:

>>> 2 or 5    # left most operand bool(2) == True
2    
>>> 0 or 5    # bool(0) == False and bool(5) == True
5
>>> 0 or ()
()

那么,这有什么用呢?下面的例子来自 《实用 Python》 由 Magnus Lie Hetland 著:
假设用户需要输入他的名字,但也可以选择不输入,这种情况下你想使用默认值 '<Unknown>'。 你可以使用 if 语句,但也可以更简洁地表达:

In [171]: name = raw_input('Enter Name: ') or '<Unknown>'
Enter Name: 

In [172]: name
Out[172]: '<Unknown>'

换句话说,如果 raw_input 的返回值为真(不是空字符串),那么就将其赋值给 name(没有变化);否则,默认值 '<Unknown>' 将被赋值给 name

438

没错,andor 这两个操作符都是短路的——你可以查看文档了解更多。

撰写回答