LoginSignup
0
0

More than 5 years have passed since last update.

python3x: generator.send(value)って何?

Last updated at Posted at 2017-05-14

When the caller executes R = m.send(a), it puts the object a into the generator's input slot, transfers control to the generator, and waits for a response. The generator receives object a as the result of X = yield i, and runs until it hits another yield expression e.g. Y = yield j. Then it puts j into its output slot, transfers control back to the caller, and waits until it gets resumed again. The caller receives j as the result of R = m.send(a), and runs until it hits another S = m.send(b) statement, and so on.

R = next(m) is just the same as R = m.send(None); it's putting None into the generator's input slot, so if the generator checks the result of X = yield i then X will be None.

coroutine.py
def coroutine():
    for i in range(1, 10):
        print("From generator {}".format((yield i)))
>>> c = coroutine()
>>> c.send(None) # same as next(c)
>>> try:
        while True:
            print("From user {}".format(c.send(1)))
    except StopIteration: pass

From generator 1
From user 2
From generator 1
From user 3
From generator 1
From user 4
...

other = yield fooは「fooyieldして返ってきたvalueotherに渡してください」というイメージ。つまりyieldしてからvalueをotherに渡すまでに若干のラグがある(ことが多い)。

yieldsendも一度処理を行うと(イメージ的には)そこで一時停止してvalueを受け取るまで次に進まない。print(yield i)yieldしたiを表示するのではなくyieldした後に返ってきたvalueを表示する。

gen.py
def foo():
    while True:
        x = yield
        print(x)

>>> gen = foo()
>>> gen.send(None) #runs up to yield statement
>>> print(gen.send("foo"))
foo
None #since nothing is yielded back inside of foo func.

def foo():
    while True:
        x = yield
        print(x)
        yield x

>>> gen = foo()
>>> gen.send(None) #runs up to yield statement
>>> print(gen.send("foo"))
foo
foo
  1. c.send(None)によりcoroutine関数内のiterationが始まる(i = 1)。print("From generator {}".format((yield i)))により1を返す。ここでストップ。※まだiのvalueが返ってきてないのでプリントはしない。iのvalue受取待ち状態。(上で示したラグ)
  2. while文へ移動。cにvalue1を送る。value受取待ち状態。
  3. c関数内へ移動。while文より送られてきたvalue1を受け取りそのvalueをプリントする。(=From generator 1)
  4. c関数内のiterationを続行。1だったi2にしてyieldする。ここでストップ。
  5. while文へ移動(ステップ2よりvalue受取待ち状態)。関数cより送られてきたi=2を受取プリントする(From user 2)。
  6. ステップ2, 3, 4...とi9になるまで繰り返す。9になるとNoneyieldしてiterationが終了する。

上でも何度か示したがgenerator.send(None)next(generator)は同じ役割を持つ。最初のyield文にたどり着くための橋渡しと考えて良い。

参考にしたリンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0