2016-04-01 11 views
4

このタイトルが良いかどうかわかりません。誰かがそれを変更するのを助けてくれることを願っています。2つ以上の同時反復をサポートする反復可能なクラスを定義する

私はmoleculeクラスを定義しようとしています。その原子を反復できることを願っています。 私は人々が反復可能なクラスを定義する方法を探索し、それは次のようになります。それがうまく機能

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 

をしかし、私は彼らが同時に存在する場合、それは、2回の反復子では動作しないことができました。 2回の反復子がそうゼロへのポインタを更新する新しいイテレータを定義し、同じself.__pointerを共有するため

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

これは驚きではありません。

私はこのページを見ていて、ほとんどの人がクラス内でself.__pointerを使用しています。これが私の質問を呼び起こします。 pointerが反復子(iteまたはite2)の属性であり、反復されたオブジェクト自体(molecule)の属性ではないと思われる場合、この問題は解決できます。

誰かがいくつかの助けを与えることを望む:)ありがとう。

答えて

2

これが呼び出されるたびに、新しいイテレータオブジェクトを返すようにします。__iter__

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) 

    ... 

それとも、あなたは__next__を定義する必要はありませんyield statementを使用することができます。 `__iter__`は、新しいイテレータオブジェクトにそれを呼び出して、すべての時間を返すようにしてくださいhttps://ideone.com/TK78Ml

+0

>:

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

DEMO:__iter__()は新しいジェネレータイテレータを返しますので。 <<どのようにする? 'yield'を使うのがよさそうです。 –

+0

@RuixingWang、最初のオプションのコードを含めるように答えを更新しました。 (新しいイテレータインスタンスを返す) – falsetru

+0

クールな答え。コメント '#Are you sure'、はい、私は1から原子を数えますが、ゼロではありません:)ありがとう! –

関連する問題