什么是生成器
通过列表推导式,可以直接创建一个列表,但是收到内存限制,列表容量肯定是有限的而且,创建一个包含100万个元素的列表,占用很大的存储空间。如果我们仅仅需要访问前面几个元素,后面 后面元素的占用存储空间就被浪费
所以,如果列表元素可以按照某种算法算出来,那我们就可以再循环当中不断地推导它,生成元素,这样就不必创建完整的list,从而大大节省了存储空间。
在Python中,这种一边循环一边计算的机制,成为生成器:generator
斐波那契数列案例实现生成器:
#数列写法:1,1,2,3,5,8
#函数写法
def fib(times):
a = 0
b = 1
n = 1
while n<=times:
print(b)
a,b = b,a+b
n += 1
fib(3)
#生成器写法
def fib(times):
a = 0
b = 1
n = 1
while n<=times:
yield b
a,b = b,a+b
n+=1
p = fib(5)
print(p)
执行的结果为:
1 #函数写法执行的结果
1 #函数写法执行的结果
2 #函数写法执行的结果
<generator object fib at 0x0000000002174468> #生成器写法执行的结果
yield 的作用就是把一个函数变成一个生成器, 带有yield的函数不再是一个普通的函数。python解释器会将其视为一个generator
调用fib(5)不会返回fib函数 而是返回一个迭代器对象,在for循环执行时,每次循环都会执行fib函数的内部代码
什么是迭代器
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一 个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
可迭代对象
以直接作用于 for 循环的数据类型有以下几种:
一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;
一类是 generator ,包括生成器和带 yield 的generator function。这些可以直接作用于 for 循环的对象统称为可迭代对象:Iterable 。
判断是否是可迭代
可以使用 isinstance() 判断一个对象是否是 Iterable 对象:
而生成器不但可以作用于 for 循环,还可以被 next() 函数不断调用并返回下一个值,直到最后抛出
StopIteration 错误表示无法继续返回下一个值了。
迭代器
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。可以使用 isinstance() 判断一个对象是否是 Iterator 对象:
iter函数
生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数:
总结:
迭代器不一定是生成器,生成器一定是迭代器
凡是可作用于 for 循环的对象都是 Iterable 类型; 凡是可作用于 next() 函数的对象都是 Iterator 类型
集合数据类型如 list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可以通过 iter() 函数获得一个Iterator 对象。