Python 是否支持短路?

Does Python support short-circuiting?

提问人:Dinah 提问时间:4/6/2010 最后编辑:dreftymacDinah 更新时间:1/27/2021 访问量:145591

问:

Python 是否支持布尔表达式中的短路?

python boolean-logic 短路

评论

1赞 cs95 1/11/2019
密切相关:“and”/“or”运算符的奇怪用法

答:

433赞 Alex Martelli 4/6/2010 #1

是的,两者都和操作员短路 - 请参阅文档andor

266赞 Grijesh Chauhan 2/15/2013 #2

操作员的短路行为: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:

        False    None    0    ""    ()    []     {}

功能中的短路行为: , :any()all()

Python 的 any() 和 all() 函数也支持短路。如文档所示;他们按顺序评估序列的每个元素,直到找到一个允许提前退出评估的结果。请考虑以下示例来理解两者。

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

>>> 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() 检查所有元素是否为 True,并在遇到 False 时立即停止执行:

>>> 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 中

比较可以任意链接;例如,等价于 ,只计算一次(但在这两种情况下,当发现为 false 时根本不计算)。x < y <= zx < y and y <= zyzx < y

>>> 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 中的逻辑运算符返回操作数的值而不是布尔值 ( 或 )。例如:
TrueFalse

操作给出结果x and yif x is false, then x, else 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 

类似地,运算符返回最左边的值,其中 == else 右边最假的值(根据短路行为),例如:orbool(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 ()
()

那么,这有什么用呢?Magnus Lie Hetland 在 Practical Python 中给出了一个例子:
假设用户应该输入他或她的名字,但可能选择不输入任何内容,在这种情况下,您希望使用默认值。 你可以使用 if 语句,但你也可以非常简洁地陈述内容:
'<Unknown>'

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

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

换句话说,如果 from 的返回值为 true(不是空字符串),则将其分配给 name(没有任何变化);否则,缺省值将指定给 。raw_input'<Unknown>'name

评论

4赞 ShadowRanger 9/25/2019
小狡辩:虚假值的明确列表略有误导性。任何类型都可以有一个或多个虚假值。按照惯例,所有带有值的数值类型都是虚假的(所以它不仅仅是 、 、 、 等),所有带有长度的集合也是如此(所以在你列出的之上,[Py3]、[Py2] 和 / 都是计算为 falsy 的内置函数),但用户定义的/第三方类型可以定义自己的类型(使用 [Py3]/[Py2] 直接定义,或通过定义间接定义)。000.00jdecimal.Decimal(0)fractions.Fraction(0)0b''u''set()frozenset()__bool____nonzero____len__
2赞 Grijesh Chauhan 9/25/2019
@ShadowRanger在这里,您的评论将完成我的回答。感谢您添加此注释。
0赞 Erik Aronesty 10/17/2019
此外,python 会双重评估短路条件,如果以后用作布尔值......除非它们位于 IF 语句中,该语句是特权的:gist.github.com/earonesty/08e9cbe083a5e0583feb8a34cc538010
0赞 Keerthana Prabhakaran 7/30/2020
python @GrijeshChauhan支持长电路?
0赞 Grijesh Chauhan 8/10/2021
@KeerthanaPrabhakaran :(对不起,我不知道。如果您发布新问题,请与我分享。
63赞 Caprooja 7/27/2013 #3

是的。在 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

评论

0赞 Royi 8/24/2023
怎么能做这样的事情?它似乎无效。myVar == 5 and continue