代码之家  ›  专栏  ›  技术社区  ›  Aaron_ab

python-yield(yield)做什么?

  •  6
  • Aaron_ab  · 技术社区  · 7 年前

    由于python 2.5,因此能够 send() , throw() , close()

    def gen():
        while True:
            x = (yield)
            if x == 3:
                print('received 3!!')
                break
            else:
                yield x
    

    def gen2():
        while True:
            yield (yield)
    

    注意到它是一个合法的生成器,可以做一些事情。。 我想弄明白的第一件事是:

    这种文字有好的用法吗?

    g = gen2()
    next(g)
    g.send(10) # output: 10
    g.send(2) # output: nothing
    g.send(3) # output: 3
    g.send(44) # output: nothing
    

    为什么每一秒“发送”都不起任何作用?

    2 回复  |  直到 6 年前
        1
  •  9
  •   ccppjava    3 年前

    yield (yield) 首次收益率 None yield . 然后,它从 send next . 内部 产量 产量 立即产生该价值。


    每个 产量 概念上有两部分:

    1. 邮寄 .
    2. 邮寄 下一个

    同样,每个 邮寄 下一个

    1. 将值传输到 产量 没有一个 下一个
    2. 从下一个接收值 表示

    系统中最令人困惑的部分可能是这些部分是交错的。a的两个部分 对应两种不同的调用 邮寄 下一个 邮寄 下一个 s

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

    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
    

    Inside the generator                      Outside the generator
    

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

    第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
    

    步骤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
    

                                              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
    
        2
  •  3
  •   BrenBarn    7 年前

    yield 是一个表达式。表达式的值是使用 .send next 已使用,而不是 .邮寄 ). 是一个方法调用,因此当然也会返回一个值,即生成器生成的值。换句话说,每次你 .邮寄 ,则会生成一个值(可能没有),并且每次 ,则发送一个值(可能为无)。

    下面是一个简单的示例:

    def gen():
        sent1 = yield 1
        print(sent1, "was sent")
        sent2 = yield 2
        print(sent2, "was sent")
        print("Reached end of generator")
    
    g = gen()
    print(next(g), "was yielded")
    print(g.send("A"), "was yielded")
    print(g.send("B"), "was yielded")
    next(g)
    
    # output
    1 was yielded
    A was sent
    2 was yielded
    B was sent
    Reached end of generator
    # StopIteration is raised here
    

    在您的示例中,第一个 下一个 产量 是内部收益率 yield (yield) send 将10作为该值传递 产量 . 每个后续值 邮寄 成为其中一个收益的值。你的一些 邮寄 None . 如上所述,当您致电 邮寄 邮寄 内在价值观 ,它将由外部 产量 print 任何操作或其他操作都会产生显式输出。)

    下面是另一个可能有启发性的例子:

    def gen():
        yield (yield (yield (yield "WHOA")))
    
    >>> g = gen()
    >>> next(g)
    'WHOA'
    >>> g.send(1)
    1
    >>> g.send(2)
    2
    >>> g.send(3)
    3
    >>> g.send(4)
    Traceback (most recent call last):
      File "<pyshell#11>", line 1, in <module>
        g.send(4)
    StopIteration
    

    产量 产生更深层嵌套的值 . 每个 产量 产量 在链条中。这将一直持续到耗尽所有产量并提高StopIteration。

    以前也有人提出过类似的问题。我的印象是,由于人们期望 邮寄 推进生成器并生成下一个结果,就像使用 . 你可以想到 next(gen) 相当于 gen.send(None) .