You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用`any`会导致Python程序挂起/运行极慢,而使用`for`循环却能高效执行?

为什么用any()的递归实现比for循环慢这么多?

先看问题场景:我们要判断能否用给定列表中的数字(可重复使用)相加得到目标金额,示例如下:

sum_possible(2017, [4, 2, 10]) # -> False

性能拉胯的any()实现

这个版本会在处理较大金额时挂起或运行极慢:

def sum_possible(amount, numbers, cache = None):
    if cache is None:
        cache = {}
    if amount in cache:
        return cache[amount]
    if amount == 0:
        return True
    if amount < 0:
        return False
    cache[amount] = any([sum_possible(amount - number, numbers, cache) for number in numbers])
    return cache[amount]

高效的for循环实现

这个版本能在合理时间内解决问题:

def sum_possible(amount, numbers, cache = None):
    if cache is None:
        cache = {}
    if amount in cache:
        return cache[amount]
    if amount == 0:
        return True
    if amount < 0:
        return False
    for number in numbers:
        if sum_possible(amount - number, numbers, cache):
            cache[amount] = True
            return True
    cache[amount] = False
    return False

核心原因:列表推导式破坏了any()的短路特性

你说的没错,any()本身是支持短路求值的——只要遇到第一个True就会立刻返回,不再检查后续元素。但问题出在你传给any()的是列表推导式:

列表推导式是贪婪求值的,它会先遍历所有numbers元素,执行每一次sum_possible(amount - number, ...)递归调用,把所有结果都计算出来并存进列表,之后any()才会开始遍历这个列表。哪怕第一个递归调用就返回了True,后面的所有递归也已经跑完了,完全没享受到短路的好处!

而for循环的实现则是真正的短路:每调用一次递归,只要返回True,立刻就会写入缓存并返回函数,后面的循环迭代直接跳过,避免了大量不必要的递归计算。

修复any()版本的小技巧

如果想保留any()的写法同时获得和for循环一样的性能,只需要把列表推导式改成生成器表达式(去掉方括号):

cache[amount] = any(sum_possible(amount - number, numbers, cache) for number in numbers)

生成器是惰性求值的,它只会在any()需要的时候才逐个生成元素,遇到第一个True就会停止生成,完美实现短路效果,性能和for循环版本几乎一致。

内容的提问来源于stack exchange,提问作者HeyZoos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 23:14:05