前言
迭代器和生成器都是对可迭代的对象进行操作。
迭代器
-
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
-
迭代器是一个可以记住遍历的位置的对象。
-
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
-
迭代器有两个基本的方法:iter() 和 next()。
迭代器的优点:
-
可节省内存空间
-
会从容器里面挨个取值,直到取完为止
迭代器的缺点
-
对迭代对象的取值不够灵活,只能从下一个开始
-
无法判断迭代器的长度
示例
list = [1,2,3,4]
nums = iter(list)
print(next(nums))
print(next(nums))
print(next(nums))
print(next(nums))
print(next(nums))
list = [1,2,3,4]
nums = iter(list)
for i in nums:
print(i)
list = [1,2,3,4]
nums = iter(list)
while True:
try:
print(next(nums))
except StopIteration:
break
生成器
-
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
-
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
-
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
-
调用一个生成器函数,返回的是一个迭代器对象。
生成器的优缺点
生成器本质上是迭代器,所以继承迭代器的所有优缺点。
生成器对比普通循环
import sys
#查看占用内存大小
mylist = [i for i in range(10000000)]
print(type(mylist))
print('列表占用内存大小:',sys.getsizeof(mylist),'字节')
mygen = (i for i in range(10000000))
print(mygen)
print('生成器占用内存大小:',sys.getsizeof(mygen),'字节')
内存大小一目了然,内存数据相差万倍。所以采用生成器能有效优化数据占用量,尤其在读取大量的日志文件能有效避免内存溢出的错误。
示例
第一种方法很简单,只要把一个列表生成式的[]改成(),就创建一个生成器(generator)。
ls = [x*x for x in range(10)]
print(type(ls))
print(ls)
ls2 = (x*x for x in range(10))
print(ls2)
for i in ls2:
print(i,end=',')
第二种方法,函数使用yield关键字,则它就是一个生成器。
yield相当于 return 返回一个值,并且记住这个返回的位置,下次迭代时,代码从yield的下一条语句开始执行。
def a(x):
for i in range(x):
yield i*i
s = a(5)
print(s)
for i in s:
print(i)
#生成器创建斐波那契数列
def fb(n):
a,b = 0,1
for i in range(n):
yield b
a,b = b,a+b
f = fb(10)
for i in f:
print(i,end=',')