如何让Python的any()和all()函数短路有效(避免在函数调用之前求值)?

问题描述 投票:0回答:2

Python 的

any
all
内置函数 应该短路,就像逻辑运算符
or
and
一样。

但是,假设我们有一个像这样的函数定义:

def func(s):
    print(s)
    return True

并使用它构建传递给

any
all
:

的值列表
>>> any([func('s'), func('t')])
's'
't'
True

由于必须在调用

any
之前构造列表,因此该函数也会提前评估,有效防止短路

如果函数调用的成本很高,那么预先评估所有函数就会造成很大的损失,并且浪费了

any
的这种能力。

知道

any
接受任何类型的iterable,我们如何推迟
func
的求值,从而使
any
的短路阻止
func(t)
的调用?

python lazy-evaluation any short-circuiting
2个回答
19
投票

我们可以使用生成器表达式,分别传递函数及其参数,并仅在生成器中进行计算,如下所示:

>>> any(func(arg) for arg in ('s', 't'))
's'
True

对于具有不同签名的不同函数,可能如下所示:

any(
    f(*args)
    for f, args in [(func1, ('s',)), (func2, (1, 't'))]
)

这样,一旦一个函数调用计算结果为

any
True
将停止迭代生成器,这意味着函数计算是完全惰性的。

推迟函数求值的另一种巧妙方法是使用 lambda 表达式,如下所示:

>>> any(
...     f() 
...     for f in [lambda: func('s'), lambda: func('t')]
... )
's'
True

0
投票

令人遗憾的是

any()
all()
没有逻辑功能并且受到这种有点人为的约束的限制。相反,一次性循环构造可能很方便,特别是在需要生成和使用中间结果的情况下。这也与提前返回的函数有关。

def example():

    for _ in range(1):
        val = func1()
        if not val:
            break
        val1 = intermediate_func1(val)
        if not func3(val1):
            break
        val2 = intermediate_func2(val1)
        if not func4(val2):
            break
        result = the_really_expensive_function(val, val2)
        if result:
            return True, result
    return False, None

使用函数和提前返回的类似构造。

def example():
    val = func1()
    if not val:
        return False, None
    val1 = intermediate_func1(val)
    if not func3(val1):
        return False, None
    val2 = intermediate_func2(val1)
    if not func4(val2):
        return False, None
    result = the_really_expensive_function(val, val2)
    if result:
        return True, result
    return False, None

我想使用什么(但不能;并且这仅适用于

:=
运算符):

if all(
        val := func1(),
        func3(val1 := intermediate_func1(val)),
        func4(val2 := intermediate_func2(val1)),
        result := the_really_expensive_function(val, val2),
        ):
    return True, result
return False, None

也许未来这是可行的。

© www.soinside.com 2019 - 2024. All rights reserved.