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

开发 后端
今天介绍生成器和yield的用法,通过如下8、9个小问题,相信大家会对它们有一点新的认识。

今天介绍生成器和yield的用法,通过如下8、9个小问题,相信大家会对它们有一点新的认识。

[[344843]]

1. 什么是可迭代对象?

可迭代对象,英文Iterable,是一个形容词,这类对象和Java语言类似,都可看作是一类接口,抽象地描述事物具备怎样的能力。所以,Iterable自然具备可迭代能力。

如下,常见的list,Iterator等都是Iterable对象:

  1. In [33]: from collections.abc import Iterable,Iterator                       
  2.  
  3. In [34]: issubclass(list,Iterable)                                           
  4. Out[34]: True 
  5.  
  6. In [35]: issubclass(Iterator,Iterable)  

2. 什么是一个生成器?

生成器是可迭代的(Iterable),最简单的创建生成器方法是通过一对(),如下所示:

  1. In [37]: g = (i*i for i in [1,4,0])                                          
  2.  
  3. In [38]: g                                                                   
  4. Out[38]: <generator object <genexpr> at 0x7fe8956e96d0> 

g 是一个生成器对象,generator object

获取生成器对象的元素,可使用next函数,如下所示,获取第一个元素:

  1. In [39]: next(g)                                                             
  2. Out[39]: 1 

获取第二个元素:

  1. In [40]: next(g)                                                             
  2. Out[40]: 16 

3. 创建生成器的几种方法?

如上所见,使用一对()能够创建一个生成器对象。

除此之外,想必大家也都知道,是使用关键字 yield. yield出现在一个函数中,运行到yield处,返回的对象便是生成器对象(generator object).

4. 生成器是迭代器吗?

生成器对象(generator object)一定也是迭代器对象(Iterator object),如上面的生成器g,使用内置函数isinstance验证,返回True:

  1. In [43]: isinstance(g,Iterator)                                              
  2. 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的函数:

  1. def gfun(): 
  2.     mylist = range(3) 
  3.     for i in mylist: 
  4.         yield i*i 
  5.  
  6. g = gfun() 
  7. print(g) 

为了加深印象,你可以自己调试验证一遍,函数第一行打的断点始终未被命中。

带yield的函数和for结合使用,第一次调用上一步创建的生成器对象后,将会进入函数体直到遇到yield返回值。

然后,for循环再进入函数时,直接跑到yield的下一句。直到生成器对象变空为止。

使用下面代码演示yield的上面过程:

  1. def createGenerator(): 
  2.     mylist = range(3) 
  3.     for i in mylist: 
  4.         yield i*i 
  5.         print(i*i) 
  6.  
  7. g = createGenerator() 
  8. print(g) 
  9. for gi  in g: 
  10.     pass 

参考录制的gif:


7. yield 都有哪些重要价值?

Python引入yield后,便拥有具备实现协程的能力,协程的确是一种高效的编程模型,关于协程的理解,后面专题会详细讨论。包括更高级的功能如异步等,根基都是yield.

8. yield 和 itertools

yield重要性和使用广泛性还提现在,Python单独一个模块专门用于管理迭代器和生成器对象,便是itertools,里面封装的方法特性后面再讨论。

9. yield 使用案例

yield实现浮点数步长的frange:

  1. def frange(start,end,step): 
  2.     i = start 
  3.     while i<end: 
  4.         yield round(i,3) 
  5.         i+=step 

调用frange:

  1. for item in frange(10,14,0.8): 
  2.     print(item) 

结果:

  1. 10 
  2. 10.8 
  3. 11.6 
  4. 12.4 
  5. 13.2 

 

责任编辑:赵宁宁 来源: Python与算法社区
相关推荐

2020-09-21 09:55:06

Python迭代器开发

2024-08-19 00:00:00

表单生成器开发开源

2019-01-24 09:46:38

PelicanPython生成器

2021-12-04 22:07:44

Python

2017-09-06 09:26:03

Python生成器协程

2023-02-07 16:11:41

2022-07-25 10:27:36

背景生成器工具前端

2012-03-30 09:31:44

WEBCSS

2024-11-11 06:10:00

Python生成器迭代器

2011-12-23 13:42:05

JavaScript

2010-09-07 16:31:17

SQL语句insert

2021-04-22 21:15:38

Generator函数生成器

2015-08-25 11:07:58

2017-07-01 16:02:39

分布式ID生成器

2022-10-17 18:29:55

2017-06-26 16:26:15

Python迭代对象迭代器

2024-11-01 15:51:06

2023-05-17 16:02:00

CSS工具代码生成器

2023-07-02 14:14:37

ChatGPTMidjourney

2021-07-23 11:24:54

Create Inc开源G代码生成器
点赞
收藏

51CTO技术栈公众号