Python--ジェネレータ

18652 ワード

学習ジェネレータの前に,まずリスト生成式を認識し,テーマに直行する必要がある.
1、簡易リスト生成の例:
1 b = [ i for i in range(10)]
2 print(b)
3 
4 >>>
5 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

NBのように見えますが、実はそれは次のようなものです.
1 c = []
2 for i in range(10):
3     c.append(i)
4 print(c)
5 
6 >>>
7 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

実はまだ少しNBの、結局コードは少なくなって、手動でにこにこします!
2、マイクロ高級点を削るリスト生成式:
1 def func(x):
2     a = x + 1
3     b = a + x
4     return b
5 d = [ func(i) for i in range(10) ]
6 print(d)
7 
8 >>>
9 [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

生成式で生成されたデータは、関数処理に渡され、所定のルールのデータのセットが得られる.
次は主役登场!!!
ジェネレータ:Pythonでループしながら計算する仕組みをジェネレータ:Generatorと呼びます.
リスト生成式により、リストを直接作成できることがわかりました.ただし、メモリの制限を受けると、リストの容量は限られているに違いありません.また、100万個の要素を含むリストを作成すると、大きなストレージスペースを消費するだけでなく、前のいくつかの要素にアクセスするだけで、後ろのほとんどの要素が消費するスペースが無駄になります.だから、リスト要素が何らかのアルゴリズムで推定できるなら、ループの過程で後続の要素を絶えず推定することができますか?これにより、listを完全に作成する必要がなくなり、大量のスペースを節約できます.
ジェネレータを作成する姿勢:生成式の[]を「()」に置き換えるとokになりますが、超簡単ではありません.の
 1 a = ( i for i in range(10))
 2 print(a)
 3 for i in a:
 4     print(i)
 5 
 6 >>>
 7  at 0x00000270A14EB0B0>
 8 0
 9 1
10 ..
11 9

上記の例から分かるように、印刷されたaはリストではなく、aのメモリアドレスである.また、aはforループによってその値を取り出すことができる.
小さな栗で生成式とジェネレータを比較しましょう.
1 #   b      
2 b = [ i for i in range(100000000) ]
3 #   c  ,          ,c           
4 c = ( i for i in range(100) )

ジェネレータのプロパティ:
1.            
2.
3. ,
4. __next__()
5.
1 c = ( i for i in range(100) )
2 print(c.__next__())
3 print(c.__next__())
4 print(c[0])
5 
6 >>>
7 0
8 1
9 TypeError: 'generator' object is not subscriptable

#############################################################
例:フィボナッチ数列の理解(次の数は最初の2つの数の和)
 1 def fib(max):
 2     n, a, b = 0, 0, 1
 3     while n < max:
 4         print(b)
 5         a, b = b, a+b  #  a, b = b, a+b     t(b,a+b);a=t[0];b=t[1],    a=b;b=a+b
 6         n = n + 1
 7     return "done"
 8 fib(7)
 9 >>>
10 1
11 1
12 2
13 3
14 5
15 8
16 13

フィボナッチ数列をジェネレータにする
 1 def fib(max):
 2     n, a, b = 0, 0, 1
 3     while n < max:
 4         yield b  #yield        ,      
 5         a, b = b, a+b
 6         n = n + 1
 7     return "---done---" 
 8 # fib(5)  #    ,     ,      。  __next__()    
 9 f = fib(5)
10 print(f.__next__())
11 print(f.__next__())
12 print(f.__next__())
13 print(f.__next__())
14 print(f.__next__())
15 print(f.__next__())
16 
17 >>>
18 1
19 1
20 2
21 3
22 5
23 StopIteration: ---done---  #       
  yield ,    __next__()  ,       ,              ,       __next__()   
 1 def fib(max):
 2     n, a, b = 0, 0, 1
 3     while n < max:
 4         # print(b)
 5         yield b  #yield        ,      
 6         a, b = b, a+b
 7         n = n + 1
 8     return "---done---"  
 9 f = fib(5)
10 f.__next__()
11 X = f.__next__()
12 print(X)
13 print("")
14 Y = f.__next__()
15 print(Y)
16 print("   ...")
17 Z = f.__next__()
18 print(Z)
19 >>>
20 1
21 22 2
23    ...
24 3

これを見ることができて、それではあなたはまたまたまた学びます:異常をつかんで、異常をつかんで、異常をつかんで、異常を捕まえます.大事なことを3回言う!!!
 1 def fib(max):
 2     n, a, b = 0, 0, 1
 3     while n < max:
 4         # print(b)
 5         yield b  #yield        ,      
 6         a, b = b, a+b
 7         n = n + 1
 8     return "---done---"
 9 g = fib(8)
10 while True:
11     try:
12         x = next(g)  #     x = g.__next__()
13         print("value:", x)
14     except StopIteration as e: #   StopIteration        
15         print("Generator return value", e.value)
16         break
17 
18 >>>
19 value: 1
20 value: 1
21 value: 2
22 value: 3
23 value: 5
24 value: 8
25 value: 13
26 value: 21
27 Generator return value ---done---

ジェネレータの例の詳細、並列化:
import  time
def consum(name):
    print("%s       " % (name))
    while True:
        baozi = yield
        print("%s    %s  " % (baozi, name))

def product(name):
    d = consum("flb")
    d2 = consum("wxl")
    d.__next__() # next  yield,   yield  
    d2.__next__()
    print("%s      " %(name))
    for i in  range(3):
        time.sleep(1)
        print("%s  %s   " %(name,i))
        d.send(i)  # send  yield,  yield  
        d2.send(i)
product("TJ")

>>>
flb       
wxl       
TJ      
TJ  0   
0    flb  
0    wxl  
TJ  1   
1    flb  
1    wxl  
TJ  2   
2    flb  
2    wxl  

END!!!