任何/所有python短路:为啥以下不起作用?
Posted
技术标签:
【中文标题】任何/所有python短路:为啥以下不起作用?【英文标题】:Any/All python short-circuit: Why doesn't the following work?任何/所有python短路:为什么以下不起作用? 【发布时间】:2020-11-09 06:10:59 【问题描述】:根据我在其他 *** 页面上看到的内容:
Does all(list) use short circuit evaluation? Do all() and any() always short-circuit in order? Is the shortcircuit behaviour of Python's any/all explicit?以下代码应该短路:
any(True, 2+2, False, 2/0)
all(True, 2+2, False, 2/0)
any([True, 2+2, False, 2/0])
all([True, 2+2, False, 2/0])
但是对于他们每个人,我都会得到一个ZeroDivisionError: division by zero
。
我错过了什么吗?为什么会出错?
【问题讨论】:
False and 2/0
和 True and 2/0
发生短路评估
【参考方案1】:
是的,python 中会发生短路
In [23]: False and 3/0
Out[23]: False
In [24]: True and 3/0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-24-a08823d6496a> in <module>
----> 1 True and 3/0
ZeroDivisionError: division by zero
使用 dis 模块,
In [32]: dis.dis("all([True, 2+2, False, 2/0])")
1 0 LOAD_NAME 0 (all)
2 LOAD_CONST 0 (True)
4 LOAD_CONST 1 (4)
6 LOAD_CONST 2 (False)
8 LOAD_CONST 3 (2)
10 LOAD_CONST 4 (0)
12 BINARY_TRUE_DIVIDE
14 BUILD_LIST 4
16 CALL_FUNCTION 1
18 RETURN_VALUE
In [33]: dis.dis("any(True, 2+2, False, 2/0)")
1 0 LOAD_NAME 0 (any)
2 LOAD_CONST 0 (True)
4 LOAD_CONST 1 (4)
6 LOAD_CONST 2 (False)
8 LOAD_CONST 3 (2)
10 LOAD_CONST 4 (0)
12 BINARY_TRUE_DIVIDE
14 CALL_FUNCTION 4
16 RETURN_VALUE
当您查看函数调用时,BINARY_TRUE_DIVIDE
在 any
或 all
之前被评估,因为表达式在任何函数调用之前首先被评估
【讨论】:
【参考方案2】:您的代码错误,因为必须对表达式进行评估才能将其传递给函数。
在这种情况下,短路实际上意味着一旦它们找到不同的值,它们就会返回并且不再检查剩余的值。这与and
和or
所做的短路类型不同,实际上可以避免计算表达式。
为了说明,让我们使用一个迭代器,它将被消耗:
>>> a = iter([1, 0, 2, 3])
>>> all(a) # Search until a falsy value
False
>>> list(a) # Show what's left in the iterator
[2, 3]
您可以看到它消耗了1
和0
,返回0
,因为它是虚假的。
现在,如果您确实想使用 any
和 all
进行惰性求值,您可以在生成器表达式中调用 lambda:
>>> any(e() for e in [lambda: 1, lambda: 0, lambda: 2/0])
True
>>> all(e() for e in [lambda: 1, lambda: 0, lambda: 2/0])
False
(感谢this question 对本文的启发。)
【讨论】:
以上是关于任何/所有python短路:为啥以下不起作用?的主要内容,如果未能解决你的问题,请参考以下文章