弄懂这6个问题,拿下Python生成器!

发表于:2020-10-10 10:13  作者:zhenguo   来源:Python与算法社区

字体: | 上一篇 | 下一篇 |我要投稿 | 推荐标签: 软件开发 Python

  1. 什么是可迭代对象?
  可迭代对象,英文Iterable,是一个形容词,这类对象和Java语言类似,都可看作是一类接口,抽象地描述事物具备怎样的能力。所以,Iterable自然具备可迭代能力。
  如下,常见的list,Iterator等都是Iterable对象:
  In [33]: from collections.abc import Iterable,Iterator         
  In [34]: issubclass(list,Iterable)                             
  Out[34]: True    
  In [35]: issubclass(Iterator,Iterable) 
  2. 什么是一个生成器?
  生成器是可迭代的(Iterable),最简单的创建生成器方法是通过一对(),如下所示:
  In [37]: g = (i*i for i in [1,4,0])                           
  In [38]: g                                                    
  Out[38]: <generator object <genexpr> at 0x7fe8956e96d0> 
  g 是一个生成器对象,generator object
  获取生成器对象的元素,可使用next函数,如下所示,获取第一个元素:
  In [39]: next(g)                                            
  Out[39]: 1
  获取第二个元素:
  In [40]: next(g)                                            
  Out[40]: 16 
  3. 创建生成器的几种方法?
  如上所见,使用一对()能够创建一个生成器对象。
  除此之外,想必大家也都知道,是使用关键字 yield. yield出现在一个函数中,运行到yield处,返回的对象便是生成器对象(generator object).
  4. 生成器是迭代器吗?
  生成器对象(generator object)一定也是迭代器对象(Iterator object),如上面的生成器g,使用内置函数isinstance验证,返回True:
  In [43]: isinstance(g,Iterator)                             
  Out[43]: True 
  因此,它具备一切迭代器的特性,关于迭代器我们已在上一个话题讨论,简而言之,迭代器的几个特点:
  ·是有去无回的,
  ·迭代器无需提前知道整个列表的所有元素,
  ·无需加载所有元素到RAM中尽而它是节省内存的(memory-efficient).
  生成器同样具备这些特性。除此之外,它还有一些独有的特性,下面跟随yield 我们便能看出来。
  5. 如何用一句话描述 yield?
  yield 关键字的用法在stackoverflow上也是最热的问题之一,借用一个最热回答中的解释:
   yield is a keyword that is used like return, except the function will return a generator.
  yield 是一个特殊的return, 它返回一个生成器对象。
  说实话,理解这些只是皮毛。那么,如何精通yield的用法呢?
  6. 如何精通yield的用法?
  要想精通yield,你必须首先搞清楚一点:
  当你调用带有yield的函数时,函数并没有执行任何一行,只是返回一个生成器对象
  为了帮助大家理解,创建一个带有yield的函数:
  def gfun(): 
      mylist = range(3) 
      for i in mylist: 
          yield i*i 
   
  g = gfun() 
  print(g)
  为了加深印象,你可以自己调试验证一遍,函数第一行打的断点始终未被命中。
  带yield的函数和for结合使用,第一次调用上一步创建的生成器对象后,将会进入函数体直到遇到yield返回值。
  然后,for循环再进入函数时,直接跑到yield的下一句。直到生成器对象变空为止。
  使用下面代码演示yield的上面过程:
  def createGenerator(): 
      mylist = range(3) 
      for i in mylist: 
          yield i*i 
          print(i*i) 
   
  g = createGenerator() 
  print(g) 
  for gi  in g: 
      pass 
  参考录制的gif:
  7. yield 都有哪些重要价值?
  Python引入yield后,便拥有具备实现协程的能力,协程的确是一种高效的编程模型,关于协程的理解,后面专题会详细讨论。包括更高级的功能如异步等,根基都是yield.
  8. yield 和 itertools
  yield重要性和使用广泛性还提现在,Python单独一个模块专门用于管理迭代器和生成器对象,便是itertools,里面封装的方法特性后面再讨论。
  9. yield 使用案例
  yield实现浮点数步长的frange:
  def frange(start,end,step): 
      i = start 
      while i<end: 
          yield round(i,3) 
          i+=step 
  调用frange:
  for item in frange(10,14,0.8): 
      print(item)
  结果:
  10 
  10.8 
  11.6 
  12.4 
  13.2 

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理

评 论

论坛新帖

顶部 底部


建议使用IE 6.0以上浏览器,800×600以上分辨率,法律顾问:上海瀛东律师事务所 张楠律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2020, 沪ICP备05003035号
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪公网安备 31010102002173号

51Testing官方微信

51Testing官方微博

扫一扫 测试知识全知道