Python難点解析---初級編3.反復(反復可能、反復可能、ジェネレータ)

6700 ワード

反復とは
Wiki定義:必要なターゲットまたは結果に近づき、到達するためのフィードバックプロセスを繰り返すアクティビティです.
プログラムでは、反復は集合要素を遍歴する方法であり、インデックス値の増加によって集合要素を遍歴することができ、反復は集合要素を遍歴する別の方法である.
次に、インデックスを使用して集合要素を巡回します.
val = [1,2,3,4,5]
for i in range(len(val)):
    retVal = val[i]

この方式はC++でよく見られ,Pythonではより簡潔な文法,すなわち反復を用いることができる.
3つのキーワード
反復といえば、Pythonでは次の3つのキーワードが言及されます.
  • Iterable(反復可能)
  • iterator(反復器)
  • generator(ジェネレータ)
  • この3つのキーワードは、最初のコードから接触したかもしれませんが、コードはそうです.
    val = [1,2,3,4,5]
    for i in val:
        print i
    

    上のfor...inは、Pythonの反復器の文法糖です.はい、今あなたはこのforが何をしたかを考え始めたかもしれません.まずこの疑問を心に置いて、私たちはまず上のいくつかのキーワードを一歩一歩解析します.
    Iterable反復可能
    まず反面の教材を見て、もし私たちがfor...in文法糖でintを遍歴したらどうなりますか??
    intVal = 1024
    for _ in intVal:
        pass
    
    >>>TypeError: 'int' object is not iterable
    

    以上のエラーから、整数タイプのオブジェクトは反復可能ではありません.つまり、for..inはiterableオブジェクトにのみ適用されます.では、どのタイプのオブジェクトがiterable(反復可能)なのでしょうか.
    Pythonで、実現しました_iter_関数のタイプはlist,tuple,dictなど反復可能である.dir関数を使用して、プロトコル関数__iter__が存在するかどうかを確認できます.
    print '__iter__' in dir(dict)
    print '__iter__' in dir(list)
    print '__iter__' in dir(tuple)
    
    >>>True                                                                                                                                                                                                                                   
    >>>True                                                                                                                                                                                                                                   
    >>>True 
    

    上記の方法では、1つのオブジェクトが反復可能であるかどうかを判断することができます.もちろん、他の接地ガスの方法もあります.
    l = [1]
    from collections import Iterable
    print isinstance(l, Iterable)  #             ,    list  
    

    iterator反復器
    反復可能なオブジェクトの場合、反復器を使用して反復する必要があります.では、反復器を得るにはどうすればいいのでしょうか.
    iter()メソッドiterメソッドを使用すると、反復可能なオブジェクトをパラメータとして入力する反復器が得られます.
    l = [1]
    o = iter(l)
    print type(o)
    >>>
    

    上のコードから、反復可能なオブジェクトをiterに渡す方法で反復器を得たことがわかりますが、この反復器があれば、どのように反復すればいいのでしょうか.
    next()メソッド
    反復器を呼び出すnextメソッドは、要素を巡回できますが、nextメソッドは無限に使用できません.
    l = [1, 2, 3]
    o = iter(l)
    print o.next()
    print o.next()
    print o.next()
    print o.next()
    
    >>>1                                                                                                                                                                                                                                      
    >>>2                                                                                                                                                                                                                                      
    >>>3                                                                                                                                                                                                                                      
    >>>Traceback (most recent call last):                                                                                                                                                                                                     
      File "e:\Microsoft VS Code\TestFiles\test.py", line 63, in                                                                                                                                                                   
        print o.next()                                                                                                                                                                                                                     
    StopIteration  
    
    next法により反復可能なオブジェクト内の要素を1つずつ巡回することができ、巡回が終了すると異常StopIterationが発生する.
    反復器クラス
    以上の方法に加えて、next__iter__の方法を実装する必要があるクラスを構築することもできます.次に、フィボナッチ数列を構築します.
    class FabIteratorClass(object):
        def __init__(self, max):
            self.m_Max = max
            self.m_Idx = 0
            self.m_a = 0
            self.m_b = 1
    
        def __iter__(self):
            return self
    
        def next(self):
            if self.m_Idx < self.m_Max:
                ret = self.m_b
                self.m_a, self.m_b = self.m_b, self.m_a + self.m_b
                self.m_Idx += 1
                return ret
            raise StopIteration()
    
    for val in FabIteratorClass(3):
        print val
    
    >>>1
    >>>1
    >>>2
    

    だから、反復器として、彼の特徴は以下の通りです.
  • は、__iter__の方法を有するか、またはiterの方法によって
  • に戻る.
  • nextメソッド
  • を有する.
  • StopIteration異常
  • を生じる.
    ビルダー
    ジェネレータといえば、必ず1つのキーワードyieldと言います.1つの関数にこのキーワードが現れたら、私たちはこの関数をジェネレータと呼びます.ジェネレータはメモリに優しい関数です.例えば、普段使っているxrange関数は、ジェネレータです.ジェネレータはすべての値を事前に生成するのではなく、必要に応じて生成します.Lazy Evaluationのやり方です.ジェネレータも反復器の一種です!
    同じフィボナッチ数列で、ジェネレータで処理します.
    def fab(max):
        idx = 0
        a = 0
        b = 1
        while idx < max:
            ret = b
            a, b = b, a + b
            idx += 1
            yield ret
    
    c = fab(5)
    print type(c)
    for val in c:
        print val
    >>> 
    >>>1                                                                                                                                                                                                                                      
    >>>1                                                                                                                                                                                                                                      
    >>>2                                                                                                                                                                                                                                      
    >>>3                                                                                                                                                                                                                                      
    >>>5 
    

    まとめ:
  • 三者の継承関係はこうである:generator--->Iterator--->Iterable
  • 反復器タイプは__iter__およびnextメソッドを実装する必要があり、生成器は特殊な反復器であり、内部で生成器プロトコルをサポートし、iter()およびnext()メソッド
  • を明確に定義する必要はない.
  • 反復器は反復可能なオブジェクトであるに違いないが、反復可能なオブジェクトは反復器
  • とは限らない.