send
メソッドがわかりません。発電機の操作に使われているとのことですが。ただし、構文は次のとおりです:generator.send(value)
。
どういうわけか、値が現在のyield
式の結果になる必要がある理由を理解できません。私は例を用意しました:
_def gen():
for i in range(10):
X = yield i
if X == 'stop':
break
print("Inside the function " + str(X))
m = gen()
print("1 Outside the function " + str(next(m)) + '\n')
print("2 Outside the function " + str(next(m)) + '\n')
print("3 Outside the function " + str(next(m)) + '\n')
print("4 Outside the function " + str(next(m)) + '\n')
print('\n')
print("Outside the function " + str(m.send(None)) + '\n') # Start generator
print("Outside the function " + str(m.send(77)) + '\n')
print("Outside the function " + str(m.send(88)) + '\n')
#print("Outside the function " + str(m.send('stop')) + '\n')
print("Outside the function " + str(m.send(99)) + '\n')
print("Outside the function " + str(m.send(None)) + '\n')
_
結果は次のとおりです。
_1 Outside the function 0
Inside the function None
2 Outside the function 1
Inside the function None
3 Outside the function 2
Inside the function None
4 Outside the function 3
Inside the function None
Outside the function 4
Inside the function 77
Outside the function 5
Inside the function 88
Outside the function 6
Inside the function 99
Outside the function 7
Inside the function None
Outside the function 8
_
まあ、率直に言って、それは私を驚かせています。
yield
ステートメントが実行されると、ジェネレーターの状態がフリーズし、_expression_list
_の値がnext
の呼び出し元に返されることがわかります。まあ、それは起こっていないようです。 gen()
内でif
ステートメントとprint
関数を実行できるのはなぜですか。X
が異なる理由をどのように理解できますか? OK。 send(77)
が77をm
に送信すると仮定します。さて、yield
式は77になります。それでは_X = yield i
_とは何ですか?そして、関数内の77が外部で発生した場合、どのように5に変換されますか?とにかく、これらのsend
およびyield
ステートメントについてどういうわけかコメントできますか?
ジェネレーターでsend
と式yield
を使用すると、コルーチンとして扱われます。順次インターリーブで実行できるが、呼び出し元と並行して実行できない別の実行スレッド。
呼び出し元がR = m.send(a)
を実行すると、オブジェクトa
がジェネレーターの入力スロットに配置され、ジェネレーターに制御が移り、応答を待ちます。ジェネレータは、_X = yield i
_の結果としてオブジェクトa
を受け取り、別のyield
式にヒットするまで実行されます。 _Y = yield j
_。次に、j
を出力スロットに入れ、制御を呼び出し元に戻し、再開されるまで待機します。呼び出し元は、R = m.send(a)
の結果としてj
を受け取り、別のS = m.send(b)
ステートメントにヒットするまで実行します。
R = next(m)
はR = m.send(None)
とまったく同じです。ジェネレーターの入力スロットにNone
を入れているので、ジェネレーターが_X = yield i
_の結果をチェックすると、X
はNone
になります。
比喩として、 ダムウェイター を考えてみましょう:
サーバーが顧客から注文を受け取ると、彼らはパッドをダムウェイターに入れ、それをキッチンにsend
し、ハッチで皿を待ちます。
_R = kitchen.send("Ham omelette, side salad")
_
シェフ(ハッチで待っていた)が注文を受け取り、料理を準備し、レストランにyield
sして、次の注文を待ちます。
_next_order = yield [HamOmelette(), SideSalad()]
_
サーバー(ハッチで待っていた)が料理を顧客に持って行き、別の注文などで戻ってきます。
サーバーとシェフの両方が注文をsend
した後または料理をyield
した後、ハッチで待機するため、一度に何かをするのは1人だけです。つまり、プロセスはシングルスレッドです。発電機の機械(ダムウェイター)がインターリーブの実行を処理するため、両側で通常の制御フローを使用できます。
特にジェネレーターでsend()
を呼び出す場合、最も混乱する部分はこの行_X = yield i
_です。実際にあなたが知る必要がある唯一のことは:
語彙レベル:next()
はsend(None)
と等しい
インタプリタレベルで:_X = yield i
_以下の行に等しい(ORDER MATTERS):
_yield i
# won't continue until next() or send() is called
# and this is also the entry point of next() or send()
X = the_input_of_send
_
そして、2行のコメントが正確な理由です。ジェネレーターはi
(yield i
)を返すため、初めてsend(None)
を呼び出す必要があります。 before値をX
に割り当てます
def gen():
i = 1
while True:
i += 1
x = yield i
print(x)
m = gen()
next(m)
next(m)
m.send(4)
結果
None
4
上記のより単純化されたコードを見てください。
あなたの混乱につながったのは 'x = yield i'ステートメントだと思います。このステートメントは、iに割り当てられたsend()メソッドから受け入れられた値を言っているのではなく、xに割り当てられています。代わりに、値iはyieldステートメントによってジェネレーターに返され、xはsend()メソッドによって割り当てられます.1つのステートメントは2つのことを同時に実行します。