【问题标题】:yield slower than return. why?收益比回报慢。为什么?
【发布时间】:2017-05-30 23:22:13
【问题描述】:

我写了两个功能相同的函数 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 在运行时更快

时间到了

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

时间到了

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

【问题讨论】:

  • 我不知道 python 的细节。但总的来说,上下文更改比函数返回更昂贵。
  • timeit 模块应该会给你更精确的结果。并且:在else 部分,你做了两件完全不同的事情!在g 中,您只需返回对列表l 的引用;在f 中,您遍历列表和yield 单独的每个项目。还有:你的输入列表l是什么?
  • 您的示例代码有错误。 for i in h(... 那应该是f,而不是h。当我更正此问题并在我的计算机上运行代码时,我得到的结果与你相反。 `
  • else部分只运行一次,不会消耗太多时间
  • @skyking: 从 python 3.3 开始你可以yield from 一个可迭代对象。

标签: python yield


【解决方案1】:

产生结果的解决方案和计算完整结果的解决方案之间存在一些重大差异。

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

yield 结果只消耗足够的内存来保存生成器和任何时刻的单个结果 - 完整的计算消耗足够的内存来一次保存所有结果。当您获得非常大的数据集时,这些数据集可以在无论大小如何运行的东西和崩溃的东西之间产生差异。

因此,每次操作的产量稍贵一些,但在您没有耗尽结果的情况下更可靠且通常更快。

【讨论】:

    【解决方案2】:

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

    Yield 是一个与 return 一样使用的关键字,只是该函数将返回一个 generator,这就是它需要时间的原因。

    关于 yeild 的作用有一个很好的解释。在 stackoverflow 上查看this 的答案。

    【讨论】:

    • 我知道 yield 的作用。它 f 函数获取参数仅迭代 1 次,但在 g 函数获取参数迭代大约 900 次
    猜你喜欢
    • 1970-01-01
    • 2022-01-12
    • 2012-09-16
    • 1970-01-01
    • 2011-05-27
    • 2012-01-14
    • 1970-01-01
    • 2018-01-23
    • 2010-12-01
    相关资源
    最近更新 更多