2016-03-26 16 views
2

Yinelenecek nesnelerin birkaç "kaynağı" olan bir yineleyici oluşturmak istiyorum. Ben __next__() yöntemini, kaynağı seçme olanağı sunan isteğe bağlı bir anahtar kelime argümanını (anahtar kelime argümanı anlamına gelmez, sadece bir kaynağı rastgele seçersiniz) verebilmeyi isterdim. daha sonra, gerçek bir yineleyici infinite_iterator yapmak def __next__(self, **kwargs): yazmak istersenBir yineleyici oluşturma ve çeşitli yineleme kaynakları arasından seçim yapın.

#!/usr/bin/env python3 

import random 

class infinite_iterator(object): 

    def __init__(self, sources): 
     self.collector = [] 
     for s in sources: 
      random.shuffle(s) 
      self.collector.append([]) 
     self.sources = sources 

    def __iter__(self): 
     return self 

    # Workaround: calling it next instead of __next__ 
    # (not the python3 way...) 
    def next(self, **kwargs): 
     sce_nb = random.choice([ n for n in range(len(self.sources)) ]) 
     if 'choice' in kwargs: 
      sce_nb = kwargs['choice'] 
     self.collector[sce_nb].append(self.sources[sce_nb][0]) 
     output = self.sources[sce_nb].pop(0) 
     # Repopulate any empty 'source' 
     if not self.sources[sce_nb]: 
      (self.sources[sce_nb], self.collector[sce_nb]) = \ 
         (self.collector[sce_nb], self.sources[sce_nb]) 
      random.shuffle(self.sources[sce_nb]) 
     return output 


S = infinite_iterator([["Adam", "Paul", "Oliver", "Aaron", "Joshua", "Jack"], 
         ["Mary", "Sophia", "Emily", "Isobel", "Grace", "Alice", "Lucy"]]) 

print("Any name: " + S.next()) 
print("Any girl's name: " + S.next(choice=1)) 
print("Any boy's name: " + S.next(choice=0)) 

Sorun şu ki: geçici bir çözüm olarak bu yetersiz kod yazdık, böylece __next__() nedenleri sorunları (aşağıya bakınız) kullanarak

bir hata (2d çizgi)

print("Any name: " + next(S)) 
print("Any girl's name: " + next(S, choice=1)) 
print("Any boy's name: " + next(S, choice=0)) 

ama olsun: Tabi ki yazmak istiyorum

TypeError: next() takes no keyword arguments 

Bu çağrı next(S, choice=1), nesne içinde tanımlı __next__() işlevini kullanır. Bu hatadan dolayı, bir yandan bunun aslında olmadığını düşünüyorum. Bu beklenebilirdi, çünkü tam olarak bir tekrar tanımı değil, çünkü sonsuz yineleyici bir "İteratör nesnesi" miras almaz (anladığım kadarıyla, böyle bir nesne yoktur). Ama başka bir yandan, sadece next(S)'u ararsam ve bu durumda, benim__next__() yöntemim gerçekten çağrılır (rastgele bir liste üzerinde yinelemeyi seçer). Son olarak, böyle bir yineleyicinin gerçekleştirilmesi için bir çözüm var mıdır? Bu değer option değişkene geçirilen alır, bu işleri

import random 
def selector(sources): 
    option = None 
    while True: 
     if option is None: 
      option = yield random.choice(random.choice(sources)) 
     else: 
      option = yield random.choice(sources[option]) 

s = selector([["Adam", "Paul", "Oliver", "Aaron", "Joshua", "Jack"], 
       ["Mary", "Sophia", "Emily", "Isobel", "Grace", "Alice", "Lucy"]]) 

print("Any name: " + next(s)) 
print("Any girl's name: " + s.send(1)) 
print("Any boy's name: " + s.send(0)) 

yolu send diyoruz her zaman geçerli:

cevap

0

bir generator (teknik olarak bir eşyordam) yaz ve Tercihlerinle geçmesine send kullanmak while döngüsünün bir sonraki iterasyonu için seçim yapmak için kullanılır.

Bunu ilk yield deyimi vurur böylece en az bir kez next arayarak bunu başlatmak gerekecek, ama bundan sonra her iki yolu (a için next veya tam rasgele seçim için send(None) veya send(option) kullanmak çalışacağız belirli kaynak

+0

Tamam, bu yüzden '__next__' işlevini şu şekilde çağırmak imkansız:' next (s, choice = 1) '? – zezollo

+0

Yineleyici protokolü (veya' next' builtin ') tanımlanmış değil, ve bu tanımı değiştiremezsiniz, o yüzden hayır, ama 'gönder' çalışır, özellikle 'ileri' kullanarak neden takıldığınızdan emin değilim. – tzaman

İlgili konular