资讯专栏INFORMATION COLUMN

[译]yield关键字都做了什么?

elisa.yang / 2916人阅读

摘要:原文我的微信公众号每日一练要理解什么是,必须理解什么是生成器。在理解生成器之前,让我们先了解迭代。直到运行到函数结尾处停止,此时如果是用则会抛出异常,如果是用则会结束循环并且不会有异常

原文:https://stackoverflow.com/que...

我的微信公众号:python每日一练

要理解什么是 yield,必须理解什么是生成器(generator)。在理解生成器之前,让我们先了解迭代。

迭代

当你建立了一个列表,你可以逐个地访问这个列表的元素,而这个访问的过程叫做迭代(iteration)

>>> mylist = [1, 2, 3]
>>> for i in mylist:
...    print(i)
1
2
3

代码中的mylist就是一个可迭代对象(iterable),当你使用列表生成式时,你就创建了一个list,同时也创建了一个可迭代对象:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
...    print(i)
0
1
4

凡是能使用for...in...语句的对象,都叫做可迭代对象,例如:liststring、文件等等

这些可迭代对象非常方便,因为你可以根据自己的需要来访问它们。但是同时也需要将所有的值存入内存当中,无论你是不是需要所有的值,可能对于一个列表[x for x in range(100000)],你仅仅想拿到里面的素数,但当这个列表生成式被执行的时候,已经将所有100000个数字存入了内存中。

生成器

生成器是一种只能迭代一次的迭代器,生成器不会一次将所有的元素存入内存中,而是一边迭代一边运算:

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...    print(i)
0
1
4

这份代码看起来和上面的代码没有什么区别。但是你不能再次执行for i in mygenerator,因为生成器只能使用一次:

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...     print(i)
...
0
1
4
>>> for i in mygenerator:
...     print(i)
...
>>>

Yield

yield的使用和return的使用没什么区别,只是yield会返回一个生成器

>>> def createGenerator():
...    mylist = range(3)
...    for i in mylist:
...        yield i*i
...
>>> mygenerator = createGenerator() # 创建一个生成器
>>> print(mygenerator) # mygenerator是一个对象!

>>> for i in mygenerator:
...     print(i)
0
1
4

当你的函数需要返回一个很大的元素集合,并且每个元素只需要用到一次的时候,使用yield会非常方便

要想理解yield,你必须理解当你调用一个包含yield的函数的时候,函数体代码并不会执行,这个函数仅仅是返回一个生成器而已

>>> def createGenerator():
...     print("head")
...     for i in range(5):
...         yield i*i
...     print("tail")
...
>>> createGenerator()

当你第一次向后迭代(用nextfor...in...语句时)这个生成器时,函数体才会从最开始执行到yield处然后返回yield的值,随后再次向后迭代,会执行剩余的代码然后再次遇到yield停止并返回值。直到运行到函数结尾处停止,此时如果是用next()则会抛出StopIteration异常,如果是用for...in...则会结束循环并且不会有异常

>>> def createGenerator():
...     print("head")
...     for i in range(5):
...         yield i*i
...     print("tail")
...
>>> g = createGenerator()
>>> next(g)
head
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
tail
Traceback (most recent call last):
  File "", line 1, in 
StopIteration

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

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

相关文章

  • [] PEP 255--简单的生成器

    摘要:第四种选择是在不同的线程中运行生产者和消费者。包含语句的函数被称为生成器函数。然后引发一个异常,表明迭代器已经耗尽。换句话说,未捕获的异常终结了生成器的使用寿命。 showImg(https://segmentfault.com/img/bVbntUq?w=4272&h=2848);我正打算写写 Python 的生成器,然而查资料时发现,引入生成器的 PEP 没人翻译过,因此就花了点时...

    894974231 评论0 收藏0
  • [] PEP 255--简单的生成器

    摘要:第四种选择是在不同的线程中运行生产者和消费者。包含语句的函数被称为生成器函数。然后引发一个异常,表明迭代器已经耗尽。换句话说,未捕获的异常终结了生成器的使用寿命。 showImg(https://segmentfault.com/img/bVbntUq?w=4272&h=2848);我正打算写写 Python 的生成器,然而查资料时发现,引入生成器的 PEP 没人翻译过,因此就花了点时...

    gaosboy 评论0 收藏0
  • [] PEP 255--简单的生成器

    摘要:第四种选择是在不同的线程中运行生产者和消费者。包含语句的函数被称为生成器函数。然后引发一个异常,表明迭代器已经耗尽。换句话说,未捕获的异常终结了生成器的使用寿命。 showImg(https://segmentfault.com/img/bVbntUq?w=4272&h=2848);我正打算写写 Python 的生成器,然而查资料时发现,引入生成器的 PEP 没人翻译过,因此就花了点时...

    tracymac7 评论0 收藏0
  • []PEP 380--子生成器的语法

    摘要:提议以下的新的生成器语法将被允许在生成器的内部使用其中表达式作用于可迭代对象,从迭代器中提取元素。子迭代器而非生成器的语义被选择成为生成器案例的合理泛化。建议如果关闭一个子迭代器时,引发了带返回值的异常,则将该值从调用中返回给委托生成器。 导语: PEP(Python增强提案)几乎是 Python 社区中最重要的文档,它们提供了公告信息、指导流程、新功能的设计及使用说明等内容。对于学习...

    xumenger 评论0 收藏0
  • []PEP 380--子生成器的语法

    摘要:提议以下的新的生成器语法将被允许在生成器的内部使用其中表达式作用于可迭代对象,从迭代器中提取元素。子迭代器而非生成器的语义被选择成为生成器案例的合理泛化。建议如果关闭一个子迭代器时,引发了带返回值的异常,则将该值从调用中返回给委托生成器。 导语: PEP(Python增强提案)几乎是 Python 社区中最重要的文档,它们提供了公告信息、指导流程、新功能的设计及使用说明等内容。对于学习...

    fevin 评论0 收藏0

发表评论

0条评论

elisa.yang

|高级讲师

TA的文章

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