yield比return慢,为什么?

3

我编写了两个函数f和g,它们的功能相同。

def f(l, count):
    if count > 1:
        for i in f(l, count-1):
            yield i + 1
    else:

        yield from l

for i in f(range(100000),900):
    pass
print('f')

并且

def g(l, count):
    if count > 1:
        tmp = []
        for i in g(l, count-1):
            tmp.append(i+1)
        return tmp
    else:
        return l
for i in g(range(100000),900):
    pass
print('f')

我认为f应该更快,但实际运行时g更快。

g的时间更短。

real    0m5.977s
user    0m5.956s
sys     0m0.020s

时间到了

real    0m7.389s
user    0m7.376s
sys     0m0.012s

1
我不了解Python的具体情况。但是在一般情况下,上下文的更改比函数返回更加昂贵。 - Alper Kucukkomurler
1
timeit 模块应该会给你更精确的结果。另外,在 else 部分,你做了两件完全不同的事情!在 g 中,你只是返回列表 l 的引用;在 f 中,你遍历列表并逐个 yield 每个项目。还有,你的输入列表 l 是什么? - hiro protagonist
1
你的示例代码有一个错误。for i in h(... 应该是 f,而不是 h。当我更正这个错误并在我的电脑上运行代码时,我得到了与你得到的相反的结果。 - Dunes
1
否则部分只会运行一次,且不能占用太多时间。 - sahama
2
@skyking:从Python 3.3开始,您可以使用yield from迭代器。 - hiro protagonist
显示剩余4条评论
2个回答

9

一个产生结果和一个计算完整结果的解决方案之间有几个重大区别。

产出值持续返回下一个结果,直到耗尽,而完整计算总是完全完成,因此如果您有一个可能会提前终止计算的测试(通常情况下),yield方法将只被调用足够的次数以满足该标准 - 这通常会导致更快的代码。

yield结果仅消耗足以在任何时刻容纳生成器和单个结果的内存 - 完整计算需要足够的内存来同时保存所有结果。当涉及到非常大的数据集时,这可能会使运行代码的能力不受大小限制,而不会导致崩溃。

因此,每个操作花费略微更多,但更加可靠,并且在您不耗尽结果的情况下通常更快。


-4

我不知道你的 h 和 g 函数在做什么,但请记住:

Yield 是一个关键字,类似于 return,但函数将返回一个 生成器,这就是它需要时间的原因。

有一个关于 yield 的精彩解释。请查看 stackoverflow 上 this 的答案。


我知道yield的作用。在函数f中,传入的参数只迭代一次,但在函数g中,传入的参数迭代了约900次。 - sahama

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接