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)两者联系
生成器也是迭代器的一种,生成器是特殊的迭代器,迭代器包含生成器。