如何有效地排出oneliner中的迭代器?

hpk*_*k42 9 python

如果我有一个迭代器it并且想要耗尽它我可以写:

for x in it:
    pass
Run Code Online (Sandbox Code Playgroud)

是否有内置或标准的库调用,允许我在单行中进行?我当然可以这样做:

list(it)
Run Code Online (Sandbox Code Playgroud)

这将从迭代器构建一个列表然后丢弃它.但我认为由于列表构建步骤效率低下.为自己编写一个帮助函数来执行空的for循环当然是微不足道的但是如果我还缺少其他东西我很好奇.

Ign*_*ams 14

itertools食谱:

    # feed the entire iterator into a zero-length deque
    collections.deque(iterator, maxlen=0)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢 - 我尝试过谷歌和 stackoverflow 搜索,但没有找到解决方案。现在应该更容易发现:)不过,“collections.exhaust_iterator”或“itertools.exhaust_iterator”会更好而且更明显。 (3认同)

Kel*_*ndy 7

2022 更新(赏金要求):标准库中没有它的“专用函数”,但deque(it, 0)仍然是最有效的。这就是为什么它被用在itertools 的consumeRecipemore-itertools 的consume函数中(点击那里的 [source])。

\n

各种提案的基准、每个元素的迭代时间、迭代itertools.repeat(None, 10**5)(使用 CPython 3.10):

\n
  2.7 ns \xc2\xb1 0.1 ns consume_deque\n  6.5 ns \xc2\xb1 0.0 ns consume_loop\n  6.5 ns \xc2\xb1 0.0 ns consume_all_if_False\n 13.9 ns \xc2\xb1 0.3 ns consume_object_in\n 27.0 ns \xc2\xb1 0.1 ns consume_all_True\n 29.4 ns \xc2\xb1 0.3 ns consume_sum_0\n 44.8 ns \xc2\xb1 0.1 ns consume_reduce\n
Run Code Online (Sandbox Code Playgroud)\n

获胜者deque是因为是 C 并且拥有一条与 elements 无关的快速路径maxlen == 0

\n

简单循环获得第二名,是 Python 迭代中最快的。之前在这里提出的其他解决方案通过对每个元素进行或多或少的工作而浪费了或多或少的时间。我添加是consume_all_if_False为了展示如何有效地执行all/ sum:有一个if False子句,这样你的生成器就不会产生任何东西。

\n

基准代码(在线尝试!):

\n
def consume_loop(it):\n    for _ in it:\n        pass\n\ndef consume_deque(it):\n    deque(it, 0)\n\ndef consume_object_in(it):\n    object() in it\n\ndef consume_all_True(it):\n    all(True for _ in it)\n\ndef consume_all_if_False(it):\n    all(_ for _ in it if False)\n\ndef consume_sum_0(it):\n    sum(0 for _ in it)\n\ndef consume_reduce(it):\n    reduce(lambda x, y: y, it)\n\nfuncs = [\n    consume_loop,\n    consume_deque,\n    consume_object_in,\n    consume_all_True,\n    consume_all_if_False,\n    consume_sum_0,\n    consume_reduce,\n]\n\nfrom timeit import default_timer as timer\nfrom itertools import repeat\nfrom collections import deque\nfrom functools import reduce\nfrom random import shuffle\nfrom statistics import mean, stdev\n\ntimes = {f: [] for f in funcs}\ndef stats(f):\n    ts = [t * 1e9 for t in sorted(times[f])[:5]]\n    return f\'{mean(ts):5.1f} ns \xc2\xb1 {stdev(ts):3.1f} ns\'\n\nfor _ in range(25):\n  shuffle(funcs)\n  for f in funcs:\n    n = 10**5\n    it = repeat(None, n)\n    t0 = timer()\n    f(it)\n    t1 = timer()\n    times[f].append((t1 - t0) / n)\n\nfor f in sorted(funcs, key=stats):\n  print(stats(f), f.__name__)\n
Run Code Online (Sandbox Code Playgroud)\n