2016-04-01 7 views
4

Bu başlığın iyi olup olmadığından emin değilim .. Birisi onu değiştirmeye yardımcı olabilir.İki veya daha fazla eşzamanlı yinelemeyi destekleyen yinelenebilir bir sınıf tanımlayın

Bir molecule sınıfını tanımlamaya çalışıyorum ve onun atomları üzerinde yineleyebileceğini umuyorum. İnsanların bir iterable sınıfını tanımlamak nasıl aranır ve bu gibi görünebilir: Bu iyi çalışıyor

class molecule(object): 
    def __init__(self,name): 
     self.__pointer=0 
     # ...something else 
    def __iter__(self): 
     self.__pointer=0 
     return self 
    def __next__(self): 
     self.__pointer+=1 
     if self.__pointer<=self.natoms: # self.natoms is defined somewhere 
       return self[self.__pointer] # suppose __getitem__ is defined to return an atom object 
     else: 
       raise StopIteration("Exceeded all atoms") 

:

>>> ben=molecule('ben') #defined a molecule 
>>> ben.addatom(...) # and defined some atoms 
>>> ite=iter(ben) 
>>> for atom in ite: 
...  print(atom) 
... 
# atom objects are correctly printed here 

Ancak, aynı anda varsa o iki yineleyiciler içinde çalışamaz bulundu . İki yineleyiciler böylece sıfıra işaretçi yenilenecek yeni yineleyici tanımlayan bir aynı self.__pointer paylaştığından

>>> ite=iter(ben) 
>>> next(ite) 
# atom1 
>>> next(ite) 
# atom2 
>>> ite2=iter(ben) 
>>> next(ite) 
# atom1 again, where atom3 is expected 
>>> next(ite2) 
# atom2, where atom1 is expected 

Bu bir sürpriz değil.

Bu sayfada How to make class iterable?'a baktım ve bunların çoğu, sorularıma cevap veren sınıfta bir self.__pointer kullanıyor. pointer yinelemenin bir özniteliği (ite veya ite2) olur, ancak yinelenen nesnenin kendisinin (molecule) bir özniteliği olursa, bu sorun çözülebilir.

Birisi biraz yardım verebilir :) Teşekkürler. Yeni yineleyici nesnesini çağırıldığında her seferinde döndürmek için __iter__'u __iter__ yapın.

cevap

2

class molecule_iterator(object): 
    def __init__(self, obj): 
     self.pointer = 0 
     self.obj = obj 

    def __next__(self): 
     self.pointer += 1 # Are you sure to do this here? 
     if self.pointer < self.obj.natoms: 
      return self.obj[self.pointer] 
     raise StopIteration() 


class molecule(object): 
    ... 

    def __iter__(self): 
     return molecule_iterator(self) 

    ... 

Veya, __next__ tanımlamak gerekmez yield statement kullanabilirsiniz. __iter__() yeni jeneratör yineleyici döndürür Çünkü:

def __iter__(self): 
    for i in range(self.natoms): 
     yield self[i + 1] 

DEMO:

+0

https://ideone.com/TK78Ml> Make '__iter__' yeni yineleyici nesne denir her zaman dönmek için. << Bunu nasıl yapmalı? "verim" kullanırken iyi görünüyor. –

+0

@RuixingWang, ilk seçenek için kodu eklemek için cevabı güncelledim. (yeni yineleyici örneğini döndür) – falsetru

+0

Serin yanıt. '' Emin misin '' yorumunda, evet, atomları 1'den değil, sıfırdan beri sayıyorum :) Teşekkürler! –