2017-01-10 28 views

Odpowiedz

26

można tylko jeździć pociągiem generator raz, po tym jak osiągnie swój cel, nie więcej przejażdżki. W twoim przypadku generator cd jest wyczerpany, a następnie nie można go ponownie powtórzyć.

list obiekty, z drugiej strony, należy utworzyć oddzielny obiekt iteracyjnej każdym razem zadzwonić iter na nich (której pętla for niejawnie robi dla Ciebie):

print(iter([1, 2, 3])) 
# <list_iterator at 0x7f18495d4c88> 

i produkować nową iterację ty mogą korzystać. Zdarza się to w dowolnym czasie, gdy wywoływana jest na nimiter; ponieważ za każdym razem tworzony jest nowy obiekt, możesz wielokrotnie przeglądać listy. Wiele przejażdżek!

W skrócie, jeśli tylko zmiana cd być listę (w ogóle, obiekt, który będzie powtórzyć przez wiele razy):

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 

to przyniesie upragnionego rezultatu tworząc świeżą iterator obiekty z cd dla każdego elementu w ab:

abcd = (e_ab + e_cd for e_ab in ab for e_cd in cd) 
print(len(list(abcd))) 
# 16 

oczywiście można to osiągnąć za pomocą product od itertools też, ale to nie ma sensu, dlaczego tak się dzieje.

14

Myślę, że dzieje się tak dlatego, że można jednorazowo powtórzyć tylko generator. Po pierwszym zapętleniu e_cd po raz pierwszy nie pojawi się nic w kolejnej iteracji cyklu zewnętrznego.

12

Gdy generator nie ma dalszych wartości do zwrócenia, zwiększa on wyjątek StopIteration. W ten sposób sygnalizują, że są gotowe. Ponieważ nie ma wbudowanego sposobu resetowania generatorów, podczas tworzenia wielostopniowego generatora z generatorów, zatrzyma się on na pierwszym napotkanym obiekcie StopIteration, zamiast powodować, że generatory potomne będą pętle, jak dzieje się to z obiektami podobnymi do list.

itertools.product() mogą przynieść oczekiwanych rezultatów (repl.it here):

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)) 
+0

Można to również zapisać jako 'map (suma, itertools.product (A, B, C, D))'. – deltab