生成器(generator):一个返回生成器迭代器的函数。它看起来像一个普通函数,除了它包含用于生成一系列可在for循环中使用的值的yield表达式或者可以使用next函数一次检索一个值。

在Python中,使用了yield的函数被称为生成器。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作。生成器函数一般是通过for循环调用,for循环自带next方法。

生成器迭代器(generator iterator):由生成器函数(generator function)创建的对象。每个yield暂时挂起处理,记住位置执行状态(包括局部变量和挂起的try语句)。当生成器迭代器恢复时,它从停止的地方开始(与每次调用都重新开始的函数相反)。

生成器表达式(generator expression):返回迭代器的表达式。它看起来像一个普通表达式,后跟一个定义循环变量、范围和可选if子句的for子句。

yield 表达式(yield expression):用在定义生成器函数或异步生成器函数,它只能在函数定义体中使用。在函数体中使用yield表达式会使该函数成为生成器。

当一个生成器函数被调用时,它返回一个称为生成器的迭代器。该生成器控制生成器函数的执行。当调用生成器的任一方法时,执行开始。此时,继续执行第一个yield表达式,在那里它再次挂起,将expression_list的值返回给生成器的调用者。挂起是指保留所有局部状态,包括局部变量的当前绑定、指令指针、内部计算堆栈以及任何异常处理的状态。当通过调用生成器的任一方法恢复执行时,该函数可以像yield表达式被另一个外部调用继续执行。恢复后的yield表达式的值取决于恢复执行的方法。如果使用__next()__(通常通过for或next()内置函数),则结果为None。否则,如果使用send(),则结果将是传递给该方法的值。

在try结构中的任何地方都允许使用yield表达式。如果生成器在完成之前没有恢复,生成器迭代器的close()方法将被调用,允许任何挂起的finally子句执行。

当使用yield from <expr>时,提供的表达式必须是可迭代的。迭代产生的值直接传递给当前生成器方法的调用者。如果底层迭代器有适当的方法,任何用send()传入的值和用throw()传入的任何异常都被传递给底层迭代器。如果不是这种情况,则send()将触发AttributeError或TypeError,而throw()将立即触发传入的异常。当底层迭代器完成时,触发的StopIteration实例的value属性成为yield表达式的值。它可以在触发StopIteration时显式设置,也可以在子迭代器是生成器时自动设置。

yield语句:在语义上等同于yield表达式。yield表达式和语句仅用在定义生成器函数中。在函数中使用yield便会创建生成器函数。

yield语句暂停函数的执行并将一个值发送回调用者,但保留足够的状态以使函数能够从停止的地方恢复。恢复后,该函数会在最后一次yield运行后立即继续执行。这允许它的代码随着时间的推移产生一系列值,而不是一次计算它们并像列表一样发送它们。

当yield表达式是赋值语句右侧的唯一表达式时,可以省略括号。

生成器迭代器方法:它们可用于控制生成器函数的执行。当生成器已经在执行时调用下面的任何生成器方法都会触发ValueError异常。

(1).generator.__next__():开始执行生成器函数或在最后一次执行的yield表达式处继续执行。当使用__next__()方法恢复生成器函数时,当前的yield表达式总是计算为None。然后继续执行下一个yield表达式,在那里生成器再次挂起,并且expression_list的值返回给__next__()的调用者。如果生成器退出而没有产生另一个值,则会触发StopIteration异常。此方法通常被隐式调用,例如通过for循环或内置的next()函数。

(2).generator.send(value):恢复执行并将value ”sends”到生成器函数中。value参数成为当前yield表达式的结果。send()方法返回生成器生成的下一个值,或者如果生成器退出而没有生成另一个值则触发StopIteration。当调用send()来启动生成器时,必须以None作为参数调用它,因为没有可以接收值的yield表达式。

(3).generator.throw(type[, value[, traceback]]):在生成器暂停时触发类型的异常,并返回生成器函数产生的下一个值。如果生成器退出而没有产生另一个值,则会触发StopIteration异常。如果生成器函数没有捕获传入的异常,或者触发不同的异常,则该异常会传递给调用者。

(4).generator.close():在生成器函数暂停的位置触发GeneratorExit。如果生成器函数随后正常退出、已关闭或触发GeneratorExit,则close返回到其调用者。如果生成器产生一个值,则会触发RuntimeError。如果生成器触发任何其它异常,则会将其传递给调用者。如果生成器由于异常或正常退出而退出,则close()不执行任何操作。

以上内容主要翻译于:7. Simple statements — Python 3.9.7 documentation

测试代码如下:

var = 1
if var == 1:# reference: https://docs.python.org/3/reference/expressions.html#yieldexprdef echo(value=None):print("Execution starts when 'next()' is called for the first time.")try:while True:try:value = (yield value)print("value:", value)except Exception as e:value = efinally:print("Don't forget to clean up when 'close()' is called.")generator = echo(1) # 此处echo函数并未真的执行,返回generator对象print("object:", generator)print(next(generator)) # 当调用next或__next__时,echo函数才正式开始执行print(next(generator))print("start send"); print(generator.send(10)); print("end send")generator.throw(TypeError, "spam")generator.close()
elif var == 2:# reference: https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-domylist = [x*x for x in range(3)]  # mylist is an iterable,  you store all the values in memoryfor i in mylist:print(i)# Generators are iterators, a kind of iterable you can only iterate over once.# Generators do not store all the values in memory, they generate the values on the flymygenerator = (x*x for x in range(3))for i in mygenerator:print(i)for i in mygenerator:print(i) # 第二次for in不会有任何值输出, generators can only be used once# yield is a keyword that is used like return, except the function will return a generatordef create_generator():print("start ...")mylist = range(3)for i in mylist:yield i*imygenerator2 = create_generator() # create a generatorprint("object:", mygenerator2) # mygenerator2 is an objectprint("value:", mygenerator2.__next__())for i in mygenerator2:print(i)for i in mygenerator2:print(i) # 第二次for in不会有任何值输出# To master yield, you must understand that when you call the function, the code you have# written in the function body does not run. The function only returns the generator object.# Then, your code will continue from where it left off each time for uses the generator.
elif var == 3:# reference: https://www.geeksforgeeks.org/use-yield-keyword-instead-return-keyword-python/# The yield statement suspends function’s execution and sends a value back to the caller, but retains enough# state to enable function to resume where it is left off. When resumed, the function continues execution# immediately after the last yield run.def simpleGeneratorFun():yield 1yield 2yield 3for value in simpleGeneratorFun():print(value)# An infinite generator function that prints next square number. It starts with 1def nextSquare():i = 1# An Infinite loop to generate squareswhile True:yield i*ii += 1 # Next execution resumes from this pointprint("object:", nextSquare())for num in nextSquare():if num > 100:breakprint(num) # the first value is 1print("go on:")print("object:", nextSquare())for num in nextSquare():if num > 200:breakprint(num) # note: the first value is still 1, instead of 121print("test finish")

GitHub:https://github.com/fengbingchun/Python_Test

Python3中生成器介绍相关推荐

  1. Python3中闭包介绍

          Python3中的闭包(closure)是一个函数对象,它记住封闭作用域(enclosing function)中的值,即使它们不存在于内存中.它是一个将函数与环境一起存储的记录.由于闭包 ...

  2. Python3中迭代器介绍

    Python中一个可迭代对象(iterable object)是一个实现了__iter__方法的对象,它应该返回一个迭代器对象(iterator object).迭代器是一个实现__next__方法的 ...

  3. Python3中异常处理和try/except,try/finally的用法

    1:Python3中异常处理介绍 在Python中当发生错误时,Python中的异常会自动触发,异常也能由代码触发和拦截,Python中有如下语句来触发,处理异常: a:try/except:拦截由P ...

  4. 详解Python3中yield生成器的用法

    这篇文章主要介绍了详解Python3中yield生成器的用法,是Python入门学习中的基础知识,需要的朋友可以参考下 任何使用yield的函数都称之为生成器,如: def count(n):whil ...

  5. Python3中collections.OrderedDict介绍

    Python3中的collections模块实现了特定目标的容器,以提供Python标准内建容器dict.list.set和tuple的替代选择,包括namedtuple.deque.ChainMap ...

  6. python3 yield 大文件_详解Python3中yield生成器的用法

    任何使用yield的函数都称之为生成器,如: def count(n): while n > 0: yield n #生成值:n n -= 1 另外一种说法:生成器就是一个返回迭代器的函数,与普 ...

  7. Python3 中打的迭代器与生成器

    迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退 ...

  8. Python3中typing模块介绍

    typing.py的源码在:https://github.com/python/cpython/blob/main/Lib/typing.py.此模块为类型提示(Type Hints)提供运行时支持( ...

  9. Python3中内置函数callable介绍

          Python3中的内置函数callable接受一个对象参数,如果此对象参数看起来可调用,则callable函数返回True,否则返回False.如果返回True,则调用仍有可能失败:但如果 ...

最新文章

  1. C 语言 结构体_finddata_t _findfirst, _findnext, _findclose 函数讲解
  2. VMWARE workstation导致母机反应变慢的现象
  3. 微服务实践沙龙-上海站
  4. AP模块NOTE修改API
  5. notifyDataSetInvalidated()和notifyDataSetChanged()有什么区别? (转载)
  6. Oracle HA 之 OGG部署流水
  7. IntelliJ IDEA 2018.2.2远程调试Tomcat的配置方法
  8. 012-centos6.5配置静态ip
  9. UVA722 LA5359 Lakes【DFS】
  10. 阿里云服务器CPU100%问题
  11. java万年历算法_寿星万年历---java算法实现
  12. 计算机的生产过程,笔记本电脑生产流程介绍 .pptx
  13. 【内网安全】445端口的入侵与扫描
  14. 兼容移动端的 Web 档案馆可视化管理系统
  15. 华为路由器没有虚拟服务器,华为路由器如何设置 华为路由器设置方法介绍【详解】...
  16. Win10经常断开网络连接的原因
  17. oracle11g shrink,shrink lob
  18. Python爬取NBA球员生涯数据及简单可视化
  19. Unity按钮按下、抬起的反应
  20. 基于 python 和 UDP 协议实现简易聊天室(多人群聊)----详细解析带字幕

热门文章

  1. C++:随笔4--对象
  2. 基于pytorch的模型压缩和模型剪枝Model Prune示例
  3. HDU - 2586 How far away LCA+tanjar离线算法
  4. C语言实现图像中值滤波与均值滤波
  5. C语言会出现的错误,c语言,能运行但是偶尔会出现些错误,请高手们帮忙看看错在哪里啦...
  6. Windows下修改jupyter默认工作路径教程
  7. 几种和边框相关的CSS样式修改
  8. 解决微信H5获取SDK授权报错提示errMsg: “config:fail,Error: 系统错误,错误码:63002,invalid signature [20200908 22:17:17][]“
  9. 如何使用VSCode汉化插件(中文)
  10. IDEA 连接MySQL数据库