生成器generator
尽管列表解析可以方便地创建列表,但会占用内存,而且容量有限(受内存影响)。如果列表元素可以按照某种算法推算出来,那我们就可以创建生成器generator
,这样就不必创建完整的list。生成的generator
可以理解为iterator
,用for
循环来迭代它。如果推算的算法比较复杂,用类似for
循环无法实现,可以用定义函数来实现。根本上来说,迭代器就是一个有nest()
方法的对象。条目全部取出后,会引发一个 StopIteration 异常。生成器表达式就好像是惰性的列表解析。
语法:
(expression for iter_val in iterator)
#语法与列表解析一样,只需把`[]`改成`()`。
例如计算文本文件中非空字符总和,如果用列表解析,内存性能会很低,用生成器表达式会很方便实惠:
sum(len(word) for line in date for word in line.split())
另一种创建生成器的方法:定义一个函数,采用yield
语句:
aa='def'
def bb():
yield 'a'
yield 'b'
yield 'c'
aa_product_bb=[x+y for x in aa for y in bb()]
# return ['da','db','dc','ea','eb','ec','fa','fb','fc']
这里在列表解析中,两个for
循环,有一个是生成器bb()
,另一个是可迭代对象。如果两个都是迭代器,就会出问题!具体的原因未知...
利用yield
语句定义fibonaci数列:
def fib(max):
n,a,b=0,0,1
while n<max:
yiled b
a,b=,b,a+b
n+=1
return 'done'
函数定义中包含yield
关键字,这个函数就不是一个普通的函数,而是一个generator
。
迭代器
可以直接用for
循环作用的数据类型有:
- 集合数据类型:
list
,tuple
,dict
,set
,str
. - generator: 生成器及带
yield
的generator function.
这些可以直接用for
循环作用的对象统称为可迭代对象Iterable
。可以用isinstance()
判断对象是否为Iterable
对象:
isinstance((x for x in range(10)),Iterable) #return True
可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
.
生成器都是Iterator
对象,但list
,dict
,str
虽然是Iterable
,却不是Iterator
,可以利用函数iter()
使它们变成Iterator
.
Iterator
可以表示一个无限大的数据流,且不会占用大内存。for
循环本质上不断调用next(0
函数实现的。
[廖雪峰网站](http://www.liaoxuefeng.com