2017-08-15 17 views
3

__iter__()機能の中で発電機(yield)を使用する利点は何ですか? Python Cookbookを読んだ後、私は、ジェネレータが余分な状態をユーザに公開するようにしたい場合は、をのメソッドとして実装し、__iter__()メソッドにジェネレータ関数コードを入れておくことを忘れないでください。__iter __()でyieldを使用する利点は何ですか?

import io 

class playyield: 
    def __init__(self,fp): 
     self.completefp = fp 

    def __iter__(self): 
     for line in self.completefp: 
      if 'python' in line: 
       yield line 

if __name__ =='__main__': 
    with io.open(r'K:\Data\somefile.txt','r') as fp: 
     playyieldobj = playyield(fp) 
     for i in playyieldobj: 
      print I 

質問

  1. 余分な状態がここで意味ありませんか?
  2. yieldの代わりに__iter__()の内部にyieldを使用する利点は何ですか?発電機能なし
+1

今 'playyield'は*反復可能*ですが、*イテレータ*クラスを記述する必要はありませんでしたので、私はそれが非常に得策ではないと言うでしょう、が、あなた、以下のような何かを行うことができ'playyied .__ iter__'はジェネレータを返します。これはイテレータです。それは非常に便利です。 –

+0

あなたの質問は文脈全体を提供するものではありません。 Python Cookbookから引用した引用は、問題と関連しています。**問題:**あなたはジェネレータ関数を定義したいと思いますが、何らかの形でユーザに公開したい余分な状態が含まれます。ここでの_extra state_は、プログラムの他の部分に関する他の情報を意味します。 –

+0

私はこの[blog post](http://nvie.com/posts/iterators-vs-generators/)をチェックすることをお勧めします。 –

答えて

2

、あなたがベストプラクティスに従うことをしたい場合は、このような何かを実装する必要があります:もちろん

In [7]: class IterableContainer: 
    ...:  def __init__(self, data=(1,2,3,4,5)): 
    ...:   self.data = data 
    ...:  def __iter__(self): 
    ...:   return IterableContainerIterator(self.data) 
    ...: 

In [8]: class IterableContainerIterator: 
    ...:  def __init__(self, data): 
    ...:   self.data = data 
    ...:   self._pos = 0 
    ...:  def __iter__(self): 
    ...:   return self 
    ...:  def __next__(self): 
    ...:   try: 
    ...:    item = self.data[self._pos] 
    ...:   except IndexError: 
    ...:    raise StopIteration 
    ...:   self._pos += 1 
    ...:   return item 
    ...: 

In [9]: container = IterableContainer() 

In [10]: for x in container: 
    ...:  print(x) 
    ...: 
1 
2 
3 
4 
5 

を、上記の例では不自然ですが、うまくいけば、あなたはポイントを得ます。発電機では、これは単純になります状態について

In [11]: class IterableContainer: 
    ...:  def __init__(self, data=(1,2,3,4,5)): 
    ...:   self.data = data 
    ...:  def __iter__(self): 
    ...:   for x in self.data: 
    ...:    yield x 
    ...: 
    ...: 

In [12]: list(IterableContainer()) 
Out[12]: [1, 2, 3, 4, 5] 

を、まあ、それはまさにそれだ - オブジェクトは、状態を持つことができ、例えば属性。実行時にその状態を操作できます。

In [19]: class IterableContainerIterator: 
    ...:  def __init__(self, data): 
    ...:   self.data = data 
    ...:   self._pos = 0 
    ...:  def __iter__(self): 
    ...:   return self 
    ...:  def __next__(self): 
    ...:   try: 
    ...:    item = self.data[self._pos] 
    ...:   except IndexError: 
    ...:    raise StopIteration 
    ...:   self._pos += 1 
    ...:   return item 
    ...:  def rewind(self): 
    ...:   self._pos = min(0, self._pos - 1) 
    ...: 

In [20]: class IterableContainer: 
    ...:  def __init__(self, data=(1,2,3,4,5)): 
    ...:   self.data = data 
    ...:  def __iter__(self): 
    ...:   return IterableContainerIterator(self.data) 
    ...: 

In [21]: container = IterableContainer() 

In [22]: it = iter(container) 

In [23]: next(it) 
Out[23]: 1 

In [24]: next(it) 
Out[24]: 2 

In [25]: it.rewind() 

In [26]: next(it) 
Out[26]: 1 

In [27]: next(it) 
Out[27]: 2 

In [28]: next(it) 
Out[28]: 3 

In [29]: next(it) 
Out[29]: 4 

In [30]: next(it) 
Out[30]: 5 

In [31]: it.rewind() 

In [32]: next(it) 
Out[32]: 1 
関連する問題