任何()懒惰地评估?

Ev.*_*nis 6 python

我正在编写一个脚本,我必须根据许多条件测试数字.如果满足任何条件,我想返回True,我想以最快的方式做到这一点.

我的第一个想法是使用any()而不是嵌套if语句或多个or链接我的条件.因为我会满意,如果任何条件是True我真的可以从any()懒惰和尽快返回真正受益.

基于以下事实:以下打印立即发生而不是在10(= 0 + 1 + 2 + 3 + 4)秒之后,我认为是.是这样的,还是我错了?

import time

def some(sec):
    time.sleep(sec)
    return True

print(any(some(x) for x in range(5)))
Run Code Online (Sandbox Code Playgroud)

Tim*_*ker 16

是的,any()并且all()在结果明确后立即中止:查看文档:

所有(迭代器)

如果iterable的所有元素都为true(或者iterable为空),则返回True.相当于:

def all(iterable):
    for element in iterable:
        if not element:
            return False
    return True
Run Code Online (Sandbox Code Playgroud)

任何(迭代器)

如果iterable的任何元素为true,则返回True.如果iterable为空,则返回False.相当于:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False
Run Code Online (Sandbox Code Playgroud)

  • 生成器表达式是惰性的,因为它仅在请求下一个项目时调用“some(x)”。“任何/全部”短路是指它只会请求项目,直到结果明确为止。你可以说 `any([some(x) for x in range(5)])` 仍然短路,但并不懒惰,因为列表理解会导致在 `range( 的所有元素上调用 `some` ) x)` 在 `any` 开始之前,但是 `any` 仍然会尽快停止检查输入列表。 (3认同)

Eug*_*ash 9

当函数all()any()函数在可迭代的第一个"真"元素上短路时,可迭代本身可以以非惰性方式构造.考虑这个例子:

>> any(x == 100 for x in range(10**8))
True
Run Code Online (Sandbox Code Playgroud)

这需要几秒钟才能在Python 2中执行,因为它range(10**8)构造了10**8个元素的列表.同样的表达式在Python 3中立即运行,其中range()是懒惰的.

  • 很好的观察 (2认同)

Kro*_*tan 6

正如Tim正确提到的那样,anyall确实会短路,但是在您的代码中,使懒惰的原因是使用generators。例如,以下代码不会很懒惰:

print(any([slow_operation(x) for x in big_list]))
Run Code Online (Sandbox Code Playgroud)

该列表将被完全构造和计算,然后才作为参数传递给any

另一方面,生成器是可迭代的,可按需计算每个项目。它们可以是表达式函数,或者有时可以手动实现为惰性迭代器