资讯专栏INFORMATION COLUMN

Python生成器next方法和send方法区别

yimo / 1900人阅读

摘要:原文和传送门如下官网传送门翻译版本恢复执行并将值发送到生成器函数中。所述值参数成为当前产量表达的结果。该方法返回由生成器产生的下一个值,或者如果生成器退出而不产生另一个值则引发。更新对生成器使用方法,解释器在底层会调用方法,也就是方法

生成器简介

python中,含有yield关键字的对象就是一个生成器,每次调用next方法时会执行到yield后面的语句,然后返回yield后面代码块的执行结果。其实也可以调用send方法
下面给个例子方便理解。

next方法
def foo():
    bar_a = yield 1         # bar_a是语句块(yield 1)的返回值,默认为None
    bar_b = yield bar_a
    yield "最后一个值,再迭代就要报StopIteration了"

f = foo()                   # 创建生成器,此时没有执行foo()里的任何语句
print(next(f))              # 从foo()里进入,一直执行到(yield 1)处,此时变量bar_a还没有创建
print(next(f))              # 先将语句块(yield 1)的返回值赋值个bar_a,此时bar_a的值是None。
                            # 然后执行到语句块(yield bar_a),bar_b也还没有被创建
print(next(f)

输出:

>>>1
>>>None
>>>最后一个值,再迭代就要报StopIteration了

可以看出,f = foo()创建生成器时,每次执行到yield时,会跳出去并将yield关键字后面的内容返回给调用者。下一次有别的调用者再次调用生成器时,会先恢复生成器上次的机器状态,再接着执行指导遇到yield或者元素迭代完毕。
而且我们可以看到bar_abar_b是语句yield 1yield bar_a的返回值,注意:不是生成器的返回值
这里有个比较绕的地方,我们用bar_a = yield 1做分析:

1是生成器的返回值。因为生成器返回yield后面的代码块

bar_a是语句yield 1的返回值,这就好比我们写

a = print("my lover")
print("a的值是:", a)

会输出:

>>>my lover
>>>a的值是: None

send方法
def foo():
    bar_a = yield 1
    bar_b = yield bar_a
    yield "最后一个值,再迭代就要报StopIteration了"

f = foo()
print(f.send(None))
print(f.send("my lover"))
print(next(f))

输出:

>>>1
>>>my lover
>>>最后一个值,再迭代就要报StopIteration了

这里f.send(None)是初始化生成器,和next(f)的效果一模一样。但是不推荐这么写,因为不规范。
注意输出的第二行是字符串my lover,而不是None。这是因为send函数带有一个参数,这个参数会覆盖yield 1语句的返回值,也就是bar_a的值现在不是None了。

FAQ

官网提到,当我们创建一个生成器时,第一次调用只能用next()或者send(None)。因为此时send传入其他参数也没有yield语句去接收。
这句话我看不懂,说的好像传入None就有yield来接收似的。各位如果明白的欢迎指点。
原文和传送门如下:

官网传送门

Resumes the execution and “sends” a value into the generator function. The value argument becomes the result of the current yield expression. The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value. When send() is called to start the generator, it must be called with None as the argument, because there is no yield expression that could receive the value.
Google翻译版本:
恢复执行并将值“发送”到生成器函数中。所述 值参数成为当前产量表达的结果。该 send()方法返回由生成器产生的下一个值,或者StopIteration如果生成器退出而不产生另一个值则引发。当send()调用启动生成器时,必须将其None作为参数调用,因为没有可以接收该值的yield表达式。

更新:
2018-11-24
对生成器使用send(None)方法,解释器在底层会调用__next__方法,也就是next()方法

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44930.html

相关文章

  • python中yield的用法详解——最简单,最清晰的解释

    摘要:程序执行,程序会从关键字那一行继续向下运行,会把这个值赋值给变量由于方法中包含方法,所以程序会继续向下运行执行方法,然后再次进入循环程序执行再次遇到关键字,会返回后面的值后,程序再次暂停,直到再次调用方法或方法。 此文转载,侵删,原文地址:https://blog.csdn.net/mieleiz... 首先,如果你还没有对yield有个初步分认识,那么你先把yield看做return...

    VPointer 评论0 收藏0
  • Python 面试」第二次更新

    摘要:结果为对于迭代器和生成器你知道哪些,它们分别应用于什么场景先介绍什么是可迭代的任何可用于循环的都是可迭代的。示例结果为,迭代器任何可以使用函数的都是迭代器,也可使用函数将可迭代对象变为迭代器。未写完,下次更新补上。 showImg(https://segmentfault.com/img/bVbuN3P); 阅读本文大约需要 8 分钟。 7.说一下 Python 中的装饰器 原理:利用...

    Yu_Huang 评论0 收藏0
  • python yield

    摘要:第二次迭代时,使用,那么,就是强行修改表达式的值为,本来是的,那么与都有返回值,它们的返回值是当前迭代遇到时,后面表达式的值,其实就是当前迭代中后面的参数。 yield 为了精通 yield ,你必须要理解:当你调用这个函数的时候,函数内部的代码并不立马执行 ,这个函数只是返回一个生成器对象,这有点蹊跷不是吗。 那么,函数内的代码什么时候执行呢?当你使用for进行迭代的时候.现在到了关...

    20171112 评论0 收藏0
  • python协程1:yield 10分钟入门

    摘要:协程定义协程的底层架构是在中定义,并在实现的。为了简化,我们会使用装饰器预激协程。执行上述代码结果如下出错的原因是发送给协程的值不能加到变量上。示例使用和方法控制协程。 最近找到一本python好书《流畅的python》,是到现在为止看到的对python高级特性讲述最详细的一本。看了协程一章,做个读书笔记,加深印象。 协程定义 协程的底层架构是在pep342 中定义,并在python2...

    MartinDai 评论0 收藏0
  • SICP Python 描述 第五章 序列协程

    摘要:消息向迭代器获取所表示的底层序列的下一个元素。为了对方法调用做出回应,迭代器可以执行任何计算来获取或计算底层数据序列的下一个元素。这个迭代器应拥有方法,依次返回序列中的每个元素,最后到达序列末尾时产生异常。 第五章 序列和协程 来源:Chapter 5: Sequences and Coroutines 译者:飞龙 协议:CC BY-NC-SA 4.0 5.1 引言 在这一章中,我...

    leap_frog 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<