我假设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
现在,如果我愿意:
from itertools import product
l = product(A(3), A(3))
print("Here")
next(l)
我希望将其作为输出:
>'Here'
>'I am at 0'
>'I am at 0'
但是我有
>'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'
我想念什么吗?
要回答您的问题,我们需要查看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)
关注此行代码:
pools = [tuple(pool) for pool in args] * repeat
通过这种方式,两个迭代器的所有元素(输入中)被转换为元组列表(仅在您首次调用next()
时,并且此时才真正创建它们。
返回您的代码,第一次调用next(l)
时,将创建迭代器的所有元素。在您的示例中,将使用以下元素创建polls
列表:
# pools: [(0, 1, 2), (0, 1, 2)]
这就是为什么获得这些输出的原因。
至于print("Here")
,要了解为什么首先打印它,您需要了解发生器的工作方式:
itertool.product()
返回一个生成器对象。直到第一个next()
刺激生成器后,生成器才执行功能代码。随后,每个调用next()
都允许您计算下一个元素,只执行一次包含关键字yield
的循环。
Here,您将找到优秀的资源来更好地了解python生成器的工作原理。