Python在项目中的实战-迭代器&生成器

一、前言

在介绍迭代器和生成器之前,我们先了解下Python的迭代和可迭代对象。
在平时的项目实践中,迭代功能非常常用与强大。一般使用循环迭代字符串、列表、元组等数据结构,这些可以迭代的数据结构又称为可迭代对象。可迭代对象分为迭代器、序列、字典三类,如下图所示:

以列表为例,实现__iter__方法迭代列表,访问列表中每一个元素,所以列表是可迭代对象。

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

列表test_list不能实现__next__方法,因为test_list不是一个迭代器。对于迭代器来说,它不仅要实现iter方法,还需要实现next方法。

>>> next(test_list)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator

ps:python的iter方法主要用来获取可迭代对象的迭代器,像函数iter()就是使用了iter方法;next主要用于不断调用迭代对象并返回它的下一个对象,函数next()使用了next方法。

二、迭代器

1、迭代器介绍

由前言中可知,迭代器是可迭代对象的子集,迭代器是可迭代对象的一个子集,是一个可以记住遍历的位置的对象。由前言我们还可以知道的是,列表此类序列实现了__iter__方法不能实现__next__方法,迭代器区别于可迭代对象的就在于next方法的实现。但是,我们可以对列表、元组等可迭代对象使用Python内置函数iter,就能使其变成迭代器。

2、迭代器创建

以列表为例,使用Python内置函数iter将列表转换成迭代器

>>> test_list = [1,2,3,4]
>>> new_test = iter(test_list)
>>> type(new_test)
<type 'listiterator'>

for循环访问

>>> for i in new_test:
...     print(i)
... 
1
2
3
4

迭代器实现next方法,通过next访问每个元素

>>> test_list = [1,2,3,4]
>>> new_test = iter(test_list)
>>> import sys
>>> while True:
...     try:
...         print (next(new_test))
...     except StopIteration:
...         sys.exit()
... 
1
2
3
4

三、生成器

1、生成器介绍

生成器是一种特殊的迭代器,使用yeild函数返回值,而不是return,同时yield语句会把你需要的值返回给调用生成器的位置,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。生成器表达式:(exp for iter_var in iterable if_exp),跟列表表达式([exp for iter_var in iterable if_exp])相似,将方括号改成了圆括号。生成器边循环边计算,适用于想要庞大数据但内存空间小的应用场景,对比与列表生成式而言,生成器更节约空间。

2、生成器创建

生成器创建有两种方式,一种是利用生成器表达式创建,另一种方式是yeild关键字创建。
方式一:使用生成器表达式创建生成器

>>> gen = (i for i in "python")
>>> type(gen)
<type 'generator'>
>>> for g in gen:
...     print(g)
... 
p
y
t
h
o
n

方式二:一般函数会使用return做返回,生成器则使用yeild关键词代替return返回,返回数据类型为生成器。具体我们看以下示例:
普通函数使用return返回,返回列表中元素数据类型。

>>> def common_fun(test_list):
...     for i in test_list:
...             return i
... 
>>> test_list = ["python", "c++", "PHP"]
>>> result = common_fun(test_list)
>>> type(result)
<type 'str'>

使用yeild关键字返回,返回数据结构为生成器,yield语句会把你需要的值返回给调用生成器的位置,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。

>>> def common_fun(test_list):
...     for i in test_list:
...             yeild i
... 
>>> test_list = ["python", "c++", "PHP"]
>>> result = common_fun(test_list)
>>> type(result)
<type 'generator'>

四、迭代器、生成器的区别

最后我们通过以上对迭代器、生成器的介绍,将这两者进行一个总结和对比,这也是在面试过程中提问率比较高的一个问题。
(1)迭代器
迭代器是可迭代对象,还是一个可以记住遍历的位置的对象,支持next()操作,每次执行next操作都能返回其中其中一个元素,直到所有元素返回则抛出StopIteration异常。
(2)生成器
使用了yeild关键字的函数都可以说是生成器,yeild返回值为生成器类型,生成器是一种特殊的迭代器,也是可迭代对象。生成器边循环边计算的特点使得在需要生成庞大数据序列时,节约了空间,在同等数据量的条件下生成器比列表表达式操作占用内存更小。
(3)两者联系
生成器也是迭代器的一种,生成器是特殊的迭代器,迭代器包含生成器。

全部评论

相关推荐

12-06 16:17
济宁学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务