Zen*_*non 6 iteration generator python-3.7
我假设当时itertools.product生成一个元素。我现在注意到这是不正确的。简单的概念证明:
Class A:
def __init__(self, n):
self.source = iter(range(n))
def __iter__(self):
return self
def __next__(self):
val = next(self.source)
print("I am at:", val)
return val
Run Code Online (Sandbox Code Playgroud)
现在,如果我这样做:
from itertools import product
l = product(A(3), A(3))
print("Here")
next(l)
Run Code Online (Sandbox Code Playgroud)
我希望有作为输出:
>'Here'
>'I am at 0'
>'I am at 0'
Run Code Online (Sandbox Code Playgroud)
但是我有
>'I am at 0'
>'I am at 1'
>'I am at 2'
>'I am at 0'
>'I am at 1'
>'I am at 2'
>'Here'
Run Code Online (Sandbox Code Playgroud)
我想念什么吗?
为了回答你的问题,我们需要看看itertools.product的实现:
def product(*args, repeat=1):
pools = [tuple(pool) for pool in args] * repeat
result = [[]]
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
Run Code Online (Sandbox Code Playgroud)
在这里你可以找到真正的C实现,但是要回答这个问题,参考python就足够了(参见底部的EXTRA段落)。
重点关注这行代码:
pools = [tuple(pool) for pool in args] * repeat
Run Code Online (Sandbox Code Playgroud)
这样,两个迭代器的所有元素(在输入中获取)都被转换为元组列表(仅在第一次调用时next()),此时它们才真正被创建。
返回到您的代码,当您next(l)第一次调用时,将创建迭代器的所有元素。在您的示例中,将创建polls包含以下元素的列表:
# pools: [(0, 1, 2), (0, 1, 2)]
Run Code Online (Sandbox Code Playgroud)
这就是你得到这些输出的原因。
至于print("Here"),要理解为什么要首先打印它,您需要了解生成器的工作原理:
itertool.product()返回一个生成器对象。生成器在被第一个 刺激之前不会执行功能代码next()。随后,每次调用都next()允许您计算下一个元素,仅执行一次包含关键字 的循环yield。
在这里您将找到优秀的资源,以更好地了解 python 生成器的工作原理。
因为笛卡尔积必须对同一元素求值多次,而迭代器不能只使用一次。
在 C 中,它创建的元组池列表与 python 等效,正如您从这段代码中看到的那样,它会被急切地求值。每个可迭代参数首先被转换为一个元组:
pools = PyTuple_New(npools);
if (pools == NULL)
goto error;
for (i=0; i < nargs ; ++i) {
PyObject *item = PyTuple_GET_ITEM(args, i);
PyObject *pool = PySequence_Tuple(item);
if (pool == NULL)
goto error;
PyTuple_SET_ITEM(pools, i, pool);
indices[i] = 0;
}
for ( ; i < npools; ++i) {
PyObject *pool = PyTuple_GET_ITEM(pools, i - nargs);
Py_INCREF(pool);
PyTuple_SET_ITEM(pools, i, pool);
indices[i] = 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
98 次 |
| 最近记录: |