Python3 中的惰性评估

lazy evaluation in Python3

假设我有一个有副作用的函数(在这个例子中,副作用是打印了一些东西)。是否有任何版本的 any() 或可迭代列表的任何构造在找到 True 结果后不会触发副作用?

例如,假设这个函数:

def a(x):
   print("A function got: " + str(x))
   return x == 2

有人可能希望这个电话会成功。当然不是:

any([
  a(i) for i in range(5)
])

打印:

A function got: 0
A function got: 1
A function got: 2
A function got: 3
A function got: 4

但我希望它打印这个:

A function got: 0
A function got: 1
A function got: 2

为什么? Range 是一个可迭代的,列表理解产生一个可迭代的,我希望 Python 将它们链接在一起并在 any() 函数停止使用时立即停止执行整个事情,一旦它应该这样做达到第一个 True.

我误会了什么?如果有的话,哪个版本会以这种方式运行?

您可以通过在列表理解中添加条件来使用以下代码

def a(x):
   print("A function got: " + str(x))

any([
  a(i) for i in range(5) if i<3 
])

无论何时使用列表,都会计算所有值。获得懒惰评估的唯一方法是将其保留为迭代器。您可以使用生成器理解来做到这一点:

any(a(i) for i in range(5))

明确地说,使用括号与 any(list(a(i) for i in range(5))) 相同。

您也可以简单地 运行 循环和 break 循环:

for i in range(5):
    if a(i):
        break

所以

def my_any(func, it):
    for i in it:
        if func(i):
            break

my_any(a, range(5))

另一个有效的解决方案如下,首先从 itertool takewhile 导入,然后,

l=list(takewhile(lambda x:a(x) is False, range(5)))