2013-04-03 11 views
5

Próbuję grupować karty tego samego koloru (koloru) i pozycjonować je wewnątrz generatorów, a następnie przechowywać je w spisie treści.Tworzenie wielu generatorów w zrozumieniu listy

Rozwiązanie, które wymyśliłem, robi to z wyjątkiem faktu, że wszystkie generatory zawierają dokładnie te same karty. Każdy pomysł, dlaczego?

Oto kod

deck=range(52) 

gens=[(i for i in deck if i%13==v) for v in range(13)] 

podstawie tego spodziewałbym na przykład:

gens[1].next() 
1 
gens[1].next() 
14 


gens[10].next() 
10 
gens[10].next() 
23 

Ale zamiast ja dostać

gens[1].next() 
12 

gens[1].next() 
25 

gens[1].next() 
38 

i wszystkie generatory w zamian listy te same wyniki.

Odpowiedz

7

Problem polega na tym, że nazwa v w wyrażeniu generującym odnosi się do tej zmiennej v w zrozumieniu listy. Tak więc, gdy kod generuje wyrażenie generowane przez generator (po wywołaniu next), analizuje zmienną v i widzi wartość 12, niezależnie od wartości v podczas tworzenia generatora.

Jeden obejście:

deck = range(52) 

def select_kth(v): 
    return (i for i in deck if i % 13 == v) 

gens = [select_kth(v) for v in range(13)] 

Ponieważ zdefiniowaliśmy funkcję, nazwa v dostaje się żyć w swoim własnym środowisku nazewnictwa i tak pozostaje około niezmodyfikowanej.

Jeśli naprawdę chciał, można zrobić to w jednym wierszu:

gens = [(lambda v: (i for i in deck if i % 13 == v))(v) for v in range(13)] 
+0

Dzięki. Ta odpowiedź i @abarnert są znakomite – jule64

5

Jeśli przekształcić równoważnych pętli zagnieżdżonych, można zobaczyć problem określania zakresu bardziej prosty sposób:

gens = [] 
for v in range(13): 
    def gen(): 
     for i in deck: 
      if i%13 == v: 
       yield i 
    gens.append(gen()) 

Kończymy z 13 generatorami związanymi z tą samą wartością: v, 12.

Rozwiązanie tutaj jest takie samo jak w przypadku każdego innego problemu z zakresu: musisz stworzyć nowy zakres z v w nim. Najprostszym sposobem jest utworzenie nowej funkcji:

gens = [(lambda x: (i for i in deck if i%13==x)(v) for v in range(13)] 
+0

miałem zamiar to usunąć, ponieważ jest to naprawdę ta sama odpowiedź co Dougala, a on dostał się tu na minutę przede mną, ale ... to ma kilka upiorów, więc myślę, że ludzie myślą, że warto tak czy inaczej ... Dougal powinien po prostu skopiować konwersję do zagnieżdżonych pętli i mieć najlepszą z obu światów w jednej odpowiedzi? – abarnert

+0

Twoja odpowiedź jest zupełnie innym sposobem wyjaśnienia tego. Zostawiłbym to. – William

+0

Podobają mi się twoje wyjaśnienia i myślę, że warto trzymać się na własną rękę, zamiast mnie kradną, nie trzeba usuwać. :) – Dougal