生成器与迭代器
迭代器Iterator直观解释迭代器就是能够将一堆数据一个个吐出来的对象而不是一次性输出。比如nums [1, 2, 3] it iter(nums) # 获取迭代器 print(next(it)) # 1 print(next(it)) # 2 print(next(it)) # 3本质定义任何一个对象要想成为迭代器需要满足以下两个方法__iter__() # 返回自身 __next__() # 返回容器的下一个元素。如果没有元素了则抛出 StopIteration 异常。自定义生成器class MyIterator: def __init__(self, n): self.n n self.cur 0 def __iter__(self): return self def __next__(self): if self.cur self.n: self.cur 1 return self.cur else: raise StopIteration if __name__ __main__: it MyIterator(3) for i in it: print(i)结果特点惰性计算用一个取一个节省内存只能往前走不能回退生成器Generator直观理解生成器是“自动帮你写好的迭代器”。不用写nextPython帮你做。因此生成器也是一种特殊的迭代器。定义方式使用yield关键字def gen(): yield 1 yield 2 yield 3 if __name__ __main__: g gen() print(g) print(next(g)) print(next(g)) print(next(g))结果执行过程函数执行到 yield 关键字暂停返回当前值下次从暂停位置继续生成器表达式类似列表推导式g (x*x for x in range(5))对比[x*x for x in range(5)] # 列表一次性全部生成 (x*x for x in range(5)) # 生成器按需生成两者对比对比点迭代器生成器定义方式类实现yield / 表达式实现难度高非常简单本质手写迭代逻辑自动生成迭代器是否惰性是是是否是迭代器✔✔生成器本身就是迭代器总结生成器 更高级、更方便的迭代器可迭代对象 (Iterable)可迭代对象 (Iterable): 像 list, dict, str 这种可以用 for 循环遍历的都是可迭代对象但它们不是迭代器。Python 规定一个对象内部实现了iter() 方法就是可迭代对象。转换: 可以用 iter() 函数把可迭代对象转成迭代器。三者之间的关系可迭代对象 Iterable ↓ 调用 __iter__() 可以得到 迭代器 Iterator ↓ 生成器是它的子类 生成器 Generatoryield和return的区别特性returnyield函数性质普通函数生成器函数 (Generator)退出机制彻底结束函数执行完毕销毁局部变量暂停执行挂起函数保存当前所有状态返回值次数只能返回 1 次或者返回一个包含多数据的元组可以返回多次每次调用返回一个值状态保存不保存状态下次调用从头开始自动保存下次调用从上次停止的地方继续内存占用高一次性返回所有数据低按需生成一次只占一个值的空间举例当你调用一个带 return 的函数时它会从第一行开始运行直到遇到 return。一旦 return 执行函数就把结果扔给调用者然后原地解散内存中的局部变量全部回收。def normal_func(): return 第一步 return 第二步 # 永远不会被执行 print(normal_func()) # 输出: 第一步当你调用带 yield 的函数时它并不会立即执行代码而是返回一个生成器对象。每次你对这个对象执行 next()它就运行到下一个 yield 处把值交给你然后原地休眠。它会记住所有的变量、当前的循环进度和执行行数。def generator_func(): yield 第一步 yield 第二步 yield 第三步 gen generator_func() print(next(gen)) # 输出: 第一步 (函数在此处暂停) print(next(gen)) # 输出: 第二步 (函数从刚才暂停的地方恢复)