Pythonジェネレータ関数の深入浅出)
Pythonジェネレータ関数の深入浅出1、ジェネレータコンセプト 1.1`yield from`文法 1.1.1例1 1.1.2例2
2、ジェネレータ関数 2.1例 3、ジェネレータ関数の実行 3.1ジェネレータ関数の実行順序 は、次の例によって理解する. 3.1.1例1 3.1.2例2 3.1.3例3 3.1.4例4 3.1.5例5 3.1.6例6 3.1.7例7 3.1.8例8 3.1.9例9
4、ジェネレータアプリケーション 4.1無限ループ 4.2カウンタ 4.3ジェネレータインタラクション 4.3.1リセット機能付きカウンタ1 4.3.2リセット機能付きカウンタ2 4.3.3リセット機能付きカウンタ3 4.4 Coroutine
1、ジェネレータの概念ジェネレータは、ジェネレータオブジェクトを指す、ジェネレータ式で得ることもできるし、 を得ることもできる.ジェネレータオブジェクト、反復可能オブジェクト、反復器 ジェネレータオブジェクトは、遅延計算、不活性評価の である.興味があるのは、以下のリンクPythonのリスト/集合/辞書解析式、ジェネレータ式、反復器、反復可能オブジェクトの奥行き を参照することができる.
1.1 Python 3.3から が追加されました. に等価である. である.本質的に を意味する.は、以下の関数から実行プロセス全体、特に を見る.
1.1.1例1
1.1.2例2
2、ジェネレータ関数関数体に に戻る.普通の関数は呼び出して、関数は直ちに実行して を実行することを知っていますジェネレータ関数呼び出しは、直ちに関数体を実行するのではなく、 を駆動する必要がある.ジェネレータ式とジェネレータ関数はいずれもジェネレータオブジェクトを得ることができるが、ジェネレータ関数はより複雑な論理 を書くことができる.
2.1例
3、ジェネレータ関数の実行ジェネレータ関数では、 に戻す.が再実行すると、次の の実行が一時停止する. に取得できない. を投げ出す.関数に表示する が放出される. が一時停止する.は、 と同様である.は が投げ出す. がポップアップされます.
3.1ジェネレータ関数の実行順序については、次の例を参照してください.
3.1.1例1
3.1.2例2
3.1.3例3
3.1.4例4
3.1.5例5
3.1.6例6
3.1.7例7と例7を比較して理解する
3.1.8例8と例8を比較して理解する
3.1.9例9ジェネレータ関数を用いてフィボナッチ数列を計算し、割り込み条件 を構成する.
4、ジェネレータ応用
4.1無限ループ
4.2カウンタ
4.3ジェネレータインタラクション Pythonは、ジェネレータオブジェクトと対話可能な方法 は に付与することができる. を実行することができる.
4.3.1リセット機能付きカウンタ1
4.3.2リセット機能付きカウンタ2
4.3.3リセット機能付きカウンタ3
4.4協程Coroutineジェネレータの高度な使い方 プロセス、スレッドより軽量であり、ユーザ空間スケジューリング関数の実装 である. Python 3 asyncioはコラボレーション実装であり、標準ライブラリ に追加されている. Python 3.5 async、awaitキーワードを使用した直接オリジナルサポートコラボレーション コパスは非プリエンプトスケジューリング である.連携スケジューリング実現構想
1、ジェネレータの概念
yield
キーワードを用いてジェネレータ関数1.1
yield from
構文yield from
文法yield from iterable
はfor item in iterable: yield
yield from
は文法を簡略化する文法糖yield from
とは、from
の後の反復可能なオブジェクトから要素を1つずつyield
ずつ取り出してfor
が外部の実行文を循環する順序1.1.1例1
def inc():
print('Before for')
for x in range(3):
print('Before yield')
yield x
print('After yield')
print('After for')
foo = inc()
for i in foo:
print(i)
Before for
Before yield
0
After yield
Before yield
1
After yield
Before yield
2
After yield
After for
1.1.2例2
def inc():
print('Before yield')
yield from range(3)
print('After yield')
foo = inc()
for i in foo:
print(i)
Before for & yield
0
1
2
After for & yield
2、ジェネレータ関数
yield
文を含む関数がジェネレータ関数であり、呼び出すとジェネレータオブジェクトnext
関数を使用してジェネレータ関数実行後に得るジェネレータオブジェクト2.1例
def inc():
for i in range(3):
yield i
print(type(inc))
print(type(inc()))
gen1 = inc()
print(type(gen1))
for x in gen1:
print(x)
print(1, '=' * 55)
for y in gen1: # for
print(y)
print(2, '*' * 55)
next(gen1) # next , StopIteration
<class 'function'>
<class 'generator'>
<class 'generator'>
0
1
2
1 =======================================================
2 *******************************************************
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-8-04af5606ee5b> in <module>
15 print(y)
16 print(2, '*' * 55)
---> 17 next(gen1) # next StopIteration
StopIteration:
3、ジェネレータ関数の実行
yield
を複数回行うことができ、yield
を1回実行するたびに実行を一時停止し、yield
式の値をyield
文に実行され、return
文は依然として関数の実行を終了することができるが、return
文の戻り値はrerurn
は、現在の関数が戻る、実行を続行できない、次の値を取得し続けることができず、StopIteration
異常return
文がない場合、ジェネレータ関数が最後まで実行する(return None
が実行されたことに相当)場合、StopIteration
異常next(generator)
は、関数の現在位置から後に遭遇する最初のyield
文に戻る、値がポップアップされ、関数実行next
の関数を再び実行し、上述の処理手順next
の関数を呼び出し続け、ジェネレータ関数が実行を終了すると(明示的または暗黙的にreturn
の文が呼び出された)、StopIteration
の異常next( function, 'DefaultValue' )
ジェネレータ関数に戻り値がない場合、エラーは報告されず、デフォルト値3.1ジェネレータ関数の実行順序については、次の例を参照してください.
3.1.1例1
#
def inc():
print('+++ Before yield +++')
yield from range(3)
print('+++ After yield +++')
print('===================')
gen = inc()
print('===================')
for x in gen:
print('I am in For Function.')
print(x)
===================
===================
+++ Before yield +++
I am in For Function.
0
I am in For Function.
1
I am in For Function.
2
+++ After yield +++
3.1.2例2
#
def inc():
for i in range(3):
print('+++ Before yield +++')
yield i
print('+++ After yield +++')
print('===================')
gen = inc()
print('===================')
print('+++++++++++++++++++')
print(next(gen))
print('+++++++++++++++++++')
for x in gen:
print('I am in For Function.')
print(x)
===================
===================
+++++++++++++++++++
+++ Before yield +++
0
+++++++++++++++++++
+++ After yield +++
+++ Before yield +++
I am in For Function.
1
+++ After yield +++
+++ Before yield +++
I am in For Function.
2
+++ After yield +++
3.1.3例3
def gen():
print('Line 1')
yield 1
print('Line 2')
yield 2
print('Line 3')
return 3
yield 4
print(1, next(gen()))
print(2, next(gen()))
g = gen()
print(3, next(g))
print(4, next(g))
print(5, next(g, 'End')) #
print(6, next(g))
Line 1
1 1
Line 1
2 1
Line 1
3 1
Line 2
4 2
Line 3
5 End
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-11-c14b5e4a2576> in <module>
16 print(4, next(g))
17 print(5, next(g, 'End'))
---> 18 print(6, next(g))
StopIteration:
3.1.4例4
def inc():
def counter():
i = 0
while True:
i += 1
print('I am in counter_function. Before yield.', i)
yield i
print('I am in counter_function. After yield.', i)
c = counter()
print('I am in inc_function.', id(c))
def inner():
print('I am in inner_function.',id(c))
return next(c) # c ,
return inner # return lambda : next(c)
g = inc()
print('1 >>>', g(), id(g))
print('=' * 55)
print('2 >>>', g(), id(g))
print('*' * 55)
print('3 >>>', g(), id(g))
def inc():
def counter():
i = 0
while True:
i += 1
print('I am in counter_function. Before yield.', i)
yield i
print('I am in counter_function. After yield.', i)
c = counter()
print('I am in inc_function.', id(c))
def inner():
print('I am in inner_function.',id(c))
return next(c) # c ,
return inner # return lambda : next(c)
g = inc()
print('1 >>>', g(), id(g))
print('=' * 55)
print('2 >>>', g(), id(g))
print('*' * 55)
print('3 >>>', g(), id(g))
I am in inc_function. 83441736
I am in inner_function. 83441736
I am in counter_function. Before yield. 1
1 >>> 1 83500776
=======================================================
I am in inner_function. 83441736
I am in counter_function. After yield. 1
I am in counter_function. Before yield. 2
2 >>> 2 83500776
*******************************************************
I am in inner_function. 83441736
I am in counter_function. After yield. 2
I am in counter_function. Before yield. 3
3 >>> 3 83500776
3.1.5例5
def counter():
count = 0
while True:
count += 1
yield count
def inc(c):
print(c, id(c))
return next(c)
c = counter()
print(c)
print(inc(c))
print(inc(c))
print(inc(c))
<generator object counter at 0x0000000004F93D48>
<generator object counter at 0x0000000004F93D48> 83443016
1
<generator object counter at 0x0000000004F93D48> 83443016
2
<generator object counter at 0x0000000004F93D48> 83443016
3
3.1.6例6
def counter():
count = 0
while True:
count += 1
yield count
def inc(c = counter()): # counter()
return next(c)
print(inc.__defaults__) # tuple
print(11111, inc(), id(inc()), sep=' ||||| ')
print(22222, inc(), id(inc()), sep=' ||||| ')
print(33333, inc(), id(inc()), sep=' ||||| ')
print(inc.__defaults__)
# ,
# inc()
(<generator object counter at 0x0000000004F935C8>,)
11111 ||||| 1 ||||| 8791271174448
22222 ||||| 3 ||||| 8791271174512
33333 ||||| 5 ||||| 8791271174576
(<generator object counter at 0x0000000004F935C8>,)
3.1.7例7
def inc():
def counter():
count = 0
while True:
count += 1
yield count
c = counter()
return next(c)
g = inc()
print(g)
print(g())
1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-24-7a9ff0468485> in <module>
12 g = inc()
13 print(g)
---> 14 print(g())
TypeError: 'int' object is not callable
3.1.8例8
def inc():
def counter():
count = 0
while True:
count += 1
yield count
c = counter() #
def fn():
return next(c)
return fn # return lambda : next(c)
g = inc()
print(g, inc)
print(g())
print(g())
print(g())
<function inc.<locals>.fn at 0x0000000008BE4318> <function inc at 0x0000000008BE4D38>
1
2
3
3.1.9例9
def fib(n):
x = 0
y = 1
count = 0
while True:
x, y = y, x + y
count += 1
if n <= count:
yield x
break
foo = fib(10)
print(foo)
for i in foo:
print(i)
print(foo)
next(foo) # ,
<generator object fib at 0x0000000008B5E348>
55
<generator object fib at 0x0000000008B5E348>
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-35-10876317642f> in <module>
14 print(i)
15 print(foo)
---> 16 next(foo)
StopIteration:
def fib():
x = 0
y = 1
while True:
yield y
x, y = y, x + y
foo = fib()
for i in range(4):
print(next(foo))
1
1
2
3
4、ジェネレータ応用
4.1無限ループ
def counter():
i = 0
while True:
i += 1
yield i
c = counter()
print(next(c))
print(next(c))
1
2
4.2カウンタ
def inc():
def counter():
i = 0
while True:
i += 1
yield i
c = counter()
def inner():
return next(c)
return inner # return lambda : next(c)
foo = inc()
for i in range(3):
print(foo())
1
2
3
4.3ジェネレータインタラクション
send
を提供する.send
メソッドを呼び出し、send
の実パラメータをyield
文に伝えることができ、この結果は等式右側で他の変数send
は、next
と同様にジェネレータの起動を推進する、4.3.1リセット機能付きカウンタ1
#
def inc():
print('-' * 55)
def counter():
i = 0
while True:
i += 1
print('*' * 55)
# , response,
# ,
if i > 1:
print('Before yield, response is {}.'.format(response))
response = yield i
print('After yield, response is {}.'.format(response))
if response is not None:
print('=' * 55)
i = response
c = counter()
return lambda x=False: next(c) if not x else c.send(0)
foo = inc()
print(foo())
print(foo())
print(foo())
print(foo(True))
print(foo())
print(foo())
-------------------------------------------------------
*******************************************************
1
After yield, response is None.
*******************************************************
Before yield, response is None.
2
After yield, response is None.
*******************************************************
Before yield, response is None.
3
After yield, response is 0.
=======================================================
*******************************************************
1
After yield, response is None.
*******************************************************
Before yield, response is None.
2
After yield, response is None.
*******************************************************
Before yield, response is None.
3
4.3.2リセット機能付きカウンタ2
#
def inc():
print('-' * 55)
def counter():
i = 0
while True:
i += 1
print('*' * 55)
if i > 1:
print('Before yield, response is {}.'.format(response))
response = yield i
print('After yield, response is {}.'.format(response))
if response is not None:
print('=' * 55)
i = response
c = counter()
def _inc(x=False):
if x == True:
return c.send(0) #next
else:
return next(c)
return _inc
# return lambda x=False: next(c) if not x else c.send(0)
foo = inc()
print(foo())
print(foo())
print(foo())
print(foo(True))
print(foo())
print(foo())
-------------------------------------------------------
*******************************************************
1
After yield, response is None.
*******************************************************
Before yield, response is None.
2
After yield, response is None.
*******************************************************
Before yield, response is None.
3
After yield, response is 0.
=======================================================
*******************************************************
1
After yield, response is None.
*******************************************************
Before yield, response is None.
2
After yield, response is None.
*******************************************************
Before yield, response is None.
3
4.3.3リセット機能付きカウンタ3
#
def counter():
count = 0
while True:
count += 1
response = yield count
print(response, '======')
if response is not None and isinstance(response, int):
count = response
c = counter()
print(next(c))
print(next(c))
print(c.send(0))
print(next(c))
print(next(c))
1
None ======
2
0 ======
1
None ======
2
None ======
3
4.4協程Coroutine
A B
next(A) ,A yield , next(B)
B next(B) , next(A),