我们发现迭代器最核心的功能就是可以通过next()函数的调用来返回下一个数据值。如果每次返回的数据值不是在一个已有的数据集合中读取的,而是通过程序按照一定的规律计算生成的,那么也就意味着可以不用再依赖一个已有的数据集合,也就是说不用再将所有要迭代的数据都一次性缓存下来供后续依次读取,这样可以节省大量的存储(内存)空间。
数学中有个著名的斐波拉契数列(Fibonacci),数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到,具体如下:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
现在我们想要通过for...in...循环来遍历迭代斐波那契数列中的前n个数。那么这个斐波那契数列我们就可以用迭代器来实现,每次迭代都通过数学计算来生成下一个数。
# 定义迭代器 class Fibonacci(object): # num:表示生成fibonacci数列的个数 def __init__(self, num): self.num = num # 保存前两个值 self.a = 0 self.b = 1 # 记录生成数列的下标 self.current_index = 0 def __iter__(self): return self # 生成下一个数据 def __next__(self): if self.current_index < self.num: result = self.a self.a, self.b = self.b, self.a + self.b self.current_index += 1 return result else: raise StopIteration # 创建迭代器 fib = Fibonacci(5) # # 获取迭代器中下一个值 # result = next(fib) # print(result) # 直接遍历迭代器 for value in fib: print(value)
执行结果:
0 1 1 2 3
当然如果你了解到了yield的工作原理了,我们就可以用特殊的迭代器,也就是生成器来完成这个看似复杂的斐波那契的迭代了
# 创建生成器的第二种方式->在def里面看到yield关键字表示就是一个生成器 # 定义生成器 def fibonacci(num): # num: 表示斐波那契数列的个数 # 保存前两个值 a = 0 b = 1 # 记录生成数列的下标 current_index = 0 print("----11----") # 循环判断条件是否成立 while current_index < num: # 生成下一个斐波那契数列 result = a a, b = b, a + b current_index += 1 print("----22----") # 代码执行到yield会暂停,把结果返回出取,再次启动生成器的时候会在暂停的位置继续往下执行 yield result print("----33----") f = fibonacci(5) # value = next(f) # print(value) # # value = next(f) # print(value) for value in f: print(value)
执行结果如下:
----11---- ----22---- 0 ok ----33---- ----22---- 1在使用生成器实现的方式中,我们将原本在迭代器
__next__方法中实现的基本逻辑放到一个函数中来实现,但是将每次迭代返回数值的return换成了yield,此时新定义的函数便不再是函数,而是一个生成器了。简单来说:只要在def中有yield关键字的 就称为 生成器