这个问题在这里已经有了答案:
Why converting list to set is faster than converting generator to set?
(1 个回答)
List comprehension vs generator expression's weird timeit results?
(3 个回答)
2年前关闭。
Python 3.6.8 (default, Oct 7 2019, 12:59:55)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.9.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: def yield_from_generator():
...: yield from (i for i in range(10000))
...:
In [2]: def yield_from_list():
...: yield from [i for i in range(10000)]
...:
In [3]: import timeit
In [4]: timeit.timeit(lambda: list(yield_from_generator()), number=10000)
Out[4]: 5.3820097140014695
In [5]: timeit.timeit(lambda: list(yield_from_list()), number=10000)
Out[5]: 4.333915593000711
我跑
yield from
发电机和 yield from
多次列举。列表版本总是提供更好的性能,而我的直觉告诉我相反的结论 - 制作列表需要即在启动时分配内存。为什么我们能注意到这样的性能差异?
最佳答案
简短的回答是表面语法使它们看起来比实际更相似
我将更详细地分解一系列功能(dis
模块对此很有帮助),我将把它们分成设置成本和每个产生值的成本。我们从:
def yield_from_generator():
yield from (i for i in range(10000))
费用是:
genexpr
的产量,它也调用 next
在 range
迭代器。注意这里有两个上下文切换接下来我们看:
def yield_from_list():
yield from [i for i in range(10000)]
费用是:
list
操作码,所以会很快list
的迭代器所以很快 接下来我们看一个类似的函数:
def yield_from_list2():
yield from list(i for i in range(10000))
这不使用特殊列表操作码并且具有生成器的双重嵌套,因此再次变慢。费用是:
list
的迭代器所以又快了最后是一个快速版本,只是强调
yield from
:def yield_from_generator2():
yield from range(10000)
费用是:
range
对象 range
直接迭代器我的笔记本电脑上所有这些的时间是:
yield_from_generator 639 µs
yield_from_list 536 µs
yield_from_list2 689 µs
yield_from_generator2 354 µs
希望现在更清楚一点。另一个版本是:
def yield_from_list3():
yield from list(range(10000))
运行时间为 401 µs,但希望更明显的是为什么它位于中间,性能方面
关于python - `yield from` 生成器与 `yield from` 列表性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60150962/