2013-04-03 30 views
5

Aynı takımın (renk) kartlarını gruplamaya çalışıyorum ve jeneratörler içinde sıralamaya çalışıyorum ve bu jeneratörler liste kavraması içinde saklıyorum.Liste anlaşması içinde birden fazla jeneratör oluşturma

Geldiğim çözüm, tüm jeneratörlerin tam olarak aynı kartları içerdiği durumlar hariç. Bir fikrin neden? İşte

Ben mesela beklenir Buna dayanarak kod

deck=range(52) 

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

geçerli:

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


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

Ama bunun yerine

gens[1].next() 
12 

gens[1].next() 
25 

gens[1].next() 
38 

Ve liste karşılığında tüm jeneratörler olsun aynı sonuçlar ..

cevap

7

Sorun, jeneratör ifadenizdeki v adının liste anlaşmasında v değişkenine atıfta bulunmasıdır. Bu nedenle, jeneratörü ifadeniz gerçekten çalışırsa (next'u aradığınızda), v değişkenine bakar ve değerini görür, v değerinin ne olursa olsun, jeneratörü yarattığınız zamandır.

Bir geçici çözüm:

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)] 

biz bir işlev tanımlanmış olduğundan, adı v kendi adlandırma çevrede yaşama alır ve böylece etrafında değiştirilmemiş kalır. Eğer gerçekten istiyorsa

, bir satırda yapabilirsiniz:

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

: Eğer eşdeğer iç içe döngüler içine bu açarsanız daha kolay kapsam sorunu görebilirsiniz

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

Teşekkürler. Bu cevap ve @abarnert 'in her ikisi de mükemmel – jule64

5

Sonuç olarak, hepsi aynı v, 12

'a bağlı 13 jeneratörler ile sonuçlanırsınız. Buradaki çözüm, başka bir kapsam belirleme sorunundakiyle aynıdır: yaratmanız gerekir İçinde v ile yeni bir kapsam. Bunu yapmanın en kolay yolu, yeni bir işlev oluşturmaktır:

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

Ben bunu silmek için gidiyordu, çünkü gerçekten Dougal'ın aynı cevap, ve o benden önce bir dakika var, ama ... bazı upvotes var, bu yüzden sanırım insanlar buna değer olduğunu düşünüyorum Yine de etrafta kalsın… Ya da belki Dougal, dönüşümü iç içe döngülere kopyalamalı ve her iki dünyanın en iyisine tek bir cevapta sahip olmalı mı? – abarnert

+0

Cevabınız bunu açıklamanın tamamen farklı bir yoludur. Onu bırakırdım. – William

+0

Açıklamanızı beğendim ve çalmamdan ziyade kendi başına kalmaya değer olduğunu düşünüyorum. :) – Dougal

İlgili konular