前言:在Python这么语言中,生成器毫无疑问是最有用的特性之一,但是却是使用的最不广泛的特性之一。

可迭代对象Iterable

Python 中任意的对象,只要它定义了迭代器的iter方法,或者定义了可以支持下标索引的getitem方法,那么它就是一个可迭代对象
更简单的理解是:可以用for循环遍历的对象就是Iterable
生成器也是可迭代对象

迭代器Iterator

对象有next()方法,并且使用next()或内置函数next(obj)能够返回连续的对象,没有数据返回时,抛出StopIteration异常,这就是一个迭代器。
Iterator迭代器只能被for循环遍历一次,再次遍历无数据返回。
将序列转换为迭代器的方法iter()
In [8]ite = iter([1,2,3]) # 将列表转换为迭代器 In [8]: next(ite) Out[8]: 1 In [9]: next(ite) Out[9]: 2 In [10]: next(ite) Out[10]: 3 In [11]: next(ite) # 没有数据时抛出异常 —————————————————————————————————————- StopIteration Traceback (most recent call last) in ——> 1 next(ite) StopIteration:

生成器generator

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
创建生成器通常有两种方法
1.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
In [13]: g = (x*x for x in range(10)) In [14]: g Out[14]: at 0x7fe6fd19d8e0>
2.生成器函数:定义yield关键字的函数调用时返回的就是生成器,generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
In [31]: def odd(): yield 1 yield 2 yield 3 In [32]: o = odd() In [33]: o Out[33]: In [42]: next(o) Out[42]: 1 In [43]: next(o) Out[43]: 2 In [44]: next(o) Out[44]: 3 In [45]: next(o) —————————————————————————————————————- StopIteration Traceback (most recent call last) in ——> 1 next(o) StopIteration:
genertator同样也能用for循环遍历,且只能遍历一次
In [47]: def odd(): …: yield 1 …: yield 2 …: yield 3 …: In [48]: o = odd() In [49]: for n in o: print(n) 1 2 3 In [50]: for n in o: print(n) # 空内容

生成器应用

  • 针对函数的列表进行优化

def fib_gen(n): a, b = 0, 1 while a < n : yield a # 数据量再大,也只是在调用时,产生一个数据,进行返回,大量减少内存使用 a, b = b, a+b fib_gen(5) ——————————

  • 针对读取大文件优化

def read_log(log_path): with open(log_path) as f: # 文件对象f是一个迭代器 for line in f: yield line # 不使用readlines()返回整个列表,直接返回生成器generator read_log(‘access_log.log’) # 返回生成器对象
更多实际应用可看https://www.zhihu.com/question/24807364,只看高分回答即可。

Iterable、Iterator、Generator判断
from collections import Iterable,Iterator,Generator
isinstance(range(5),Iterable) # 返回True range(5)是可迭代对象
isinstance(range(5),Iterator) # 返回False range(5)不是迭代器

isinstance([1,2,4],Iterable) # 返回True,列表为可迭代对象
isinstance([1,2,4],Iterator) # 返回False,列表不是迭代器

isinstance(open(‘test.txt’),Iterable) # 返回True,文件对象是Iterable
isinstance(open(‘test.txt’),Iterator) # 返回True,文件对象是Iterator
isinstance(open(‘test.txt’),Generator) # 返回False,文件对象不是Generator