任何/所有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/0True 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_DIVIDEanyall 之前被评估,因为表达式在任何函数调用之前首先被评估

【讨论】:

【参考方案2】:

您的代码错误,因为必须对表达式进行评估才能将其传递给函数。

在这种情况下,短路实际上意味着一旦它们找到不同的值,它们就会返回并且不再检查剩余的值。这与andor 所做的短路类型不同,实际上可以避免计算表达式。

为了说明,让我们使用一个迭代器,它将被消耗:

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

您可以看到它消耗了10,返回0,因为它是虚假的。


现在,如果您确实想使用 anyall 进行惰性求值,您可以在生成器表达式中调用 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短路:为啥以下不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 Python 中逆变换不起作用?

SwiftUI 为啥 Picker 上的输入不起作用?

Python:为啥这个程序不起作用?

为啥这个显式 P/Invoke 不起作用?

为啥我的 while 循环中的条件在 python 中不起作用?

为啥这个简单的 pyqtgraph 示例不起作用?