Python3 中是否有内置的 `take(iterable, n)` 函数?

Is there a built-in `take(iterable, n)` function in Python3?

我只是在一些嵌套生成器中滥用 StopIteration(使用 CPython 3.6.9),没有启用 PEP 479from __future__ import generator_stop),并且有一些糟糕的黑客代码使用 next(iter(iterable)) 过早地发出停止信号。

虽然 PEP 479 会捕获 StopIteration 从生成器中冒出来的问题,但我想我仍然会 运行 进入嵌套的 for 循环。

现在,我将用以下内容替换 next(iter(...)) 的所有用法:

def take(iterable, *, n):
    """
    Robustly gets the first n items from an iterable and returns them as a
    list.

    You should always use this function in lieu of `next(iter(...))`! e.g.
    instead of:

        my_first = next(iter(container))

    you should instead do:

        my_first, = take(container, n=1)

    Throws RuntimeError if the iterable cannot yield n items.
    """
    iterator = iter(iterable)
    out = []
    for _ in range(n):
        try:
            out.append(next(iterator))
        except StopIteration:
            raise RuntimeError("Premature StopIteration encountered!")
    return out

我的问题是:Python 的标准库中是否已经有这样的函数?

我在 itertoolsbuiltins 中检查了 python.org 的最新文档(3.9),我能看到的最接近的东西是 takewhile,但是嗯那。我也可以转换为 list 或任何其他可索引容器,但我想避免为了访问第一件事而需要遍历所有内容。

itertools.islice 这样做(以及更多),如果没有生成足够的元素,则不会转换为列表或出错。

您可以根据这个干净地编写您的函数:

def take(iterable, *, n):
    li = list(itertools.islice(iterable, n))
    if len(li) != n:
        raise RuntimeError("too short iterable for take")
    return li