python - yield(yield)有什么作用?

Aar*_*_ab 5 python yield generator

因为Python 2.5有能力send(),throw(),close()为发电机.在定义的生成器内部,可以通过执行以下操作来"捕获"发送的数据:

def gen():
    while True:
        x = (yield)
        if x == 3:
            print('received 3!!')
            break
        else:
            yield x
Run Code Online (Sandbox Code Playgroud)

我想要玩的是做类似的事情:

def gen2():
    while True:
        yield (yield)
Run Code Online (Sandbox Code Playgroud)

注意到它是一个合法的发电机做某事.我想弄清楚的第一件事是:

这种写作有很好的用法吗?

在做类似的事情时:

g = gen2()
next(g)
g.send(10) # output: 10
g.send(2) # output: nothing
g.send(3) # output: 3
g.send(44) # output: nothing
Run Code Online (Sandbox Code Playgroud)

为什么每秒'发送'什么都不做?

use*_*ica 7

yield (yield)首先None来自内心yield.然后它从send或接收值next.内部yield评估此接收值,外部yield立即产生该值.


每个yield概念上都有两个部分:

  1. 将值传送给send或的调用者next.
  2. 从下一个接收值sendnext致电.

同样,每个sendnext概念上都有两个部分:

  1. 将值传递给yield生成器当前暂停的表达式.(此值适用Nonenext.)
  2. 从下一个yield表达式接收值.

系统中最令人困惑的部分可能是这些部分交错.a的两个部分yield对应于sendor的两个不同的调用next,并且a的两个部分sendnext对应于两个不同的yields.

如果我们通过一个简单的例子:

def gen():
    print('Not ran at first')
    yield (yield)

g = gen()  # Step 1
print(next(g))  # Step 2
print(g.send(1)  # Step 3
g.send(2)  # Step 4
Run Code Online (Sandbox Code Playgroud)

事情就是这样:

Inside the generator                      Outside the generator
Run Code Online (Sandbox Code Playgroud)

步骤1

                                          g calls gen()
g returns a generator object 
without executing the print
just yet statement.
                                          >>> g
                                          <generator object gen at 0x7efe286d54f8>
Run Code Online (Sandbox Code Playgroud)

第2步

                                          next(g) sends None to g
g receives None, ignores it
  (since it is paused at the start
   of the function)

g prints ('not ran at first')

g executes the "transmit" phase
  of the inner yield, transmitting
  None
                                          next(g) receives None
Run Code Online (Sandbox Code Playgroud)

第3步

                                          g.send(1) sends 1 to g
g executes the "receive" phase
  of the inner yield, receiving 1
g executes the "transmit" phase
  of the outer yield, transmitting 1
                                          g.send(1) receives 1 from g
Run Code Online (Sandbox Code Playgroud)

第4步

                                          g.send(2) sends 2 to g
g executes the "receive" phase
  of the outer yield, receiving 2
g reaches the end of gen and raises
  a StopIteration
                                          g.send(2) raises the StopIteration
                                          from g
Run Code Online (Sandbox Code Playgroud)