product是否会延迟评估其参数

product是否会延迟评估其参数

本文介绍了itertools.product是否会延迟评估其参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下内容在Python 3.6中从不打印任何内容

The following never prints anything in Python 3.6

from itertools import product, count

for f in product(count(), [1,2]):
    print(f)

相反,它只是坐在那里烧CPU.问题似乎在于,如果product在无限空间内,则它永远不会返回迭代器,因为它首先评估完整的product.鉴于product应该是生成器,这令人惊讶.

Instead, it just sits there and burns CPU. The issue seems to be that product never returns an iterator if it's over an infinite space because it evaluates the full product first. This is surprising given that the product is supposed to be a generator.

我希望它会开始计数(直到无穷大),类似于此生成器的行为(取为直接从文档中获取):

I would have expected this to start counting up (to infinity), something like the behavior of this generator (taken directly from the docs):

for tup in ((x,y) for x in count() for y in [1,2]):
    print(tup)

但是,尽管我的生成器立即开始计数,但使用product的生成器却根本不计数.

But whereas my generator starts counting immediately, the one using product never counts at all.

itertools中的其他工具可以达到我的期望.例如,以下内容:

Other tools in itertools do what I'd expect. For example, the following:

for f in takewhile(lambda x: True, count()):
    print(f)

将打印数字流,因为takewhile是惰性的.

will print a stream of numbers because takewhile is lazy.

推荐答案

itertools.product 延迟生成其结果,但是对于参数而言并非如此.他们得到了热切的评价.每个可迭代的参数都首先转换为元组:

itertools.product generates its results lazily, but this is not true for the arguments. They are evaluated eagerly. Each iterable argument is first converted to a tuple:

对参数的求值(而不是结果的产生)与文档中显示的Python实现非常相似:

The evaluation of the arguments (not the production of results) is very similar to the Python implementation shown in the docs:

...
pools = [tuple(pool) for pool in args] * repeat

CPython实现中,pools是元组的元组:

for (i=0; i < nargs ; ++i) {
     PyObject *item = PyTuple_GET_ITEM(args, i);
     PyObject *pool = PySequence_Tuple(item);   /* here */
     if (pool == NULL)
         goto error;
     PyTuple_SET_ITEM(pools, i, pool);
     indices[i] = 0;
 }

之所以这样,是因为product有时需要遍历一次以上的迭代,如果将参数留作只能被使用一次的迭代器,则不可能做到这一点.

This is so since product sometimes needs to go over an iterable more than once, which is not possible if the arguments were left as iterators that can only be consumed once.

您实际上不能从itertools.count对象构建元组.在传递给product之前,考虑使用itertools.islice切片合理长度.

You practically cannot build a tuple from an itertools.count object. Consider slicing to a reasonable length with itertools.islice before passing to product.

这篇关于itertools.product是否会延迟评估其参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 18:12