Pythonの反復器とジェネレータ


Pythonの反復器とジェネレータ
まず反復器はstring,list,dict,tupleなどのコンテナオブジェクトに対してforループループを用いるのが便利である.バックグラウンドfor文でコンテナオブジェクトに対してiter()関数を呼び出し、iter()はpythonの内蔵関数です.iter()は、コンテナ内の要素に1つずつアクセスするnext()メソッドを定義した反復器オブジェクトを返します.next()もpythonの内蔵関数です.後続の要素がない場合、next()はStopIteration例外を放出し、for文ループの終了を通知します.例:
>>> s = 'abc'
>>> it = iter(s)
>>> it

>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
 File "", line 1, in 
StopIteration

pythonが持参したコンテナオブジェクトは、対応する反復メソッドを実現していますが、カスタムクラスであれば、遍歴する必要がありますか?方法はとても簡単で、この種類のAClassに対して、1つの__を実現しますiter__(self)メソッドを使用して、__付きのメソッドを返します.next__(self)メソッドのオブジェクトでいいです.もしあなたがAClassでちょうど定義していたら_next__(self)メソッド(一般的に反復器を使用して定義されます)、それは_iter__にはselfを戻せばいいだけです.くだらないことは言わないで、まずコードをつけます.
class Fib(object):
  def __init__(self, max):
    super(Fib, self).__init__()
    self.max = max

  def __iter__(self):
    self.a = 0
    self.b = 1
    return self

  def __next__(self):
    fib = self.a
    if fib > self.max:
      raise StopIteration
    self.a, self.b = self.b, self.a + self.b
    return fib

def main():
  fib = Fib(100)
  for i in fib:
    print(i)

if __name__ == '__main__':
  main()

コードが何をするかを簡単に説明し、fibonacciシーケンスを生成するためのFibクラスを定義します.for遍歴で生成されたfibonacci数を1つずつ印刷し、maxは生成されたfibonacciシーケンスの数値サイズの上限である.
クラスのインプリメンテーションでは、1つの__が定義されています.iter__(self)メソッド.このメソッドは、遍歴時にiter()に呼び出され、反復器を返す.遍歴時に直接呼び出されるpython内蔵関数iter()であるため、iter()によって呼び出される_iter__(self)オブジェクトの反復器を取得します.反復器があれば、要素を1つずつ遍歴することができます.また,逐次遍歴する場合も,内蔵next()関数を用いてオブジェクトを呼び出す_next__(self)メソッドは、反復オブジェクトを巡回します.だから実現するiter__(self)と_next__(self).そして実現したのでnext__(self)ということで実現しています_iter__(self)の場合は、直接selfに戻ればいいです.
より理解するために、カスタムコンテナオブジェクトをループするときにpython内蔵関数iter()を使用してループオブジェクトの__を呼び出すと、上記のセクションを簡単に繰り返します.iter__(self)反復器を取得し、その後、この反復器に対してnext()を使用して反復器オブジェクトを呼び出す_を再循環するnext__(self).__iter__一度だけ呼び出されますが、_next__n回呼び出されます.
次にジェネレータについて説明します.
ジェネレータ(Generator)は、反復器を作成する簡単で強力なツールです.正規の関数のように書かれていますが、データを返す必要があるときにyield文を使用します.next()が呼び出されるたびに、ジェネレータは文が最後に実行した位置とすべてのデータ値を記憶する離脱した位置を返します.次の例では、ジェネレータが簡単に作成できることを示します.
>>> def reverse(data):
...   for index in range(len(data)-1, -1, -1):
...     yield data[index]
... 
>>> for char in reverse('hello'):
...   print(char)
... 
o
l
l
e
h

反復器と生成器の違いについては、生成器は反復器ができることをすべてすることができ、自動的に作成されたためです.iter__()とnext()メソッドでは,ジェネレータが特に簡潔であり,ジェネレータも効率的である.プログラムの状態を作成して保存する自動メソッドに加えて、ジェネレータが終了すると、StopIteration異常が自動的に放出されます.yield付き関数は、通常の関数とは異なり、generatorを生成して関数呼び出しのように見えますが、next()を呼び出す(forループで自動的にnext()を呼び出す)まで関数コードは実行されません.実行プロセスは関数のプロセスで実行されますが、yield文が実行されるたびに中断され、反復値が返され、次回の実行時にyieldの次の文から実行されます.1つの関数が正常に実行されている間にyieldによって数回中断されたように見えますが、中断するたびにyieldによって現在の反復値が返されます(yieldは関数を一時停止し、next()はその一時停止から実行を再開します).
さらに、pythonは、yield値と類似した匿名関数のジェネレータ式も提供します.式自体はリストのように表示されますが、角カッコではなく丸カッコで囲まれています.
参照元:
Pythonの反復器とジェネレータhttp://www.aichengxu.com/view/63145
>>> unique_characters = {'E', 'D', 'M', 'O', 'N', 'S', 'R', 'Y'}
>>> gen = (ord(c) for c in unique_characters)
>>> gen
 at 0x7f2be4668678>
>>> for i in gen:
...   print(i)
... 
69
79
83
77
82
78
89
68
>>>

必要に応じて、ジェネレータ式をtuple、list、またはsetに渡して、すべての値を反復し、メタグループ、リスト、またはセットを返すことができます.この場合、ジェネレータ式ord(c)for c in unique_を直接charactersはtuple()などの関数に伝えればよいが,Pythonはジェネレータ式であると推定する.
最後に、ジェネレータを使用する理由は?効率のためです.リスト解析の代わりにジェネレータ式を使用すると、cpuとメモリ(ram)を同時に節約できます.リストを作成する目的が他の関数(例えばtuple()やset()に渡す)だけであれば、ジェネレータ式で置き換えましょう.
Python学習チュートリアル:http://www.aichengxu.com/item/15