使用以下代码:
A = [1, 2]
B = [-2, -1]
C = [-1, 2]
D = [0, 2]
ab = (a + b for a in A for b in B)
cd = (c + d for c in C for d in D)
abcd = (e_ab + e_cd for e_ab in ab for e_cd in cd)
Run Code Online (Sandbox Code Playgroud)
该len(abcd)预期是16,但它实际上是4.如果我使用列表理解,问题就会消失.这是为什么?
Jim*_*ard 27
您只能乘坐发电机列车一次,到达目的地后,不再乘坐.在您的情况下,cd生成器已耗尽,然后无法再次迭代.
list另一方面,对象每次调用iter它们时都会创建一个单独的迭代器对象(for循环为您隐式执行):
print(iter([1, 2, 3]))
# <list_iterator at 0x7f18495d4c88>
Run Code Online (Sandbox Code Playgroud)
并生产一个你可以使用的新鲜迭代器.这种情况发生的任何时间 iter在其上被调用; 由于每次都会生成一个新对象,因此您可以多次浏览列表.多次游乐设施!
简而言之,如果您只是更改cd为一个列表(通常,将多次迭代的对象):
ab = (a + b for a in A for b in B)
cd = [c + d for c in C for d in D] # list-comp instead
Run Code Online (Sandbox Code Playgroud)
它将通过cd为每个元素创建新的迭代器对象来产生想要的结果ab:
abcd = (e_ab + e_cd for e_ab in ab for e_cd in cd)
print(len(list(abcd)))
# 16
Run Code Online (Sandbox Code Playgroud)
当然你也可以通过实现这个product来自itertools太多,但,这是超越了为什么发生这种情况的地步.
Our*_*rus 12
当生成器没有其他值返回时,它会引发StopIteration异常.这就是他们发出信号的信号.由于没有内置的方法来重置生成器,当您从生成器创建多级生成器时,它将在第一次遇到时停止,StopIteration而不是像子列表对象那样导致子生成器循环.
itertools.product()可以产生预期的结果(在这里 repl.it ):
import itertools
A = [1, 2]
B = [-2, -1]
C = [-1, 2]
D = [0, 2]
ab = (a + b for a in A for b in B)
cd = (c + d for c in C for d in D)
abcd = (e_ab + e_cd for e_ab, e_cd in itertools.product(ab,cd))
Run Code Online (Sandbox Code Playgroud)