Python可迭代对象、迭代器、生成器
转自:http://www.langzi.fun/迭代器与生成器.html
迭代器和可迭代对象
Iterable:可迭代对象,必须要实现iter或getitem魔法函数
Iterator:迭代器对象,必须有next魔法方法。
关于for执行原理:
注意:只有实现了iter或getitem才能使用for循环
例如:for i in test:
1.先在test找iter魔法方法,并返回迭代器对象;迭代对象的next魔法方法
2.若没有iter魔法方式,则创建一个默认迭代器;迭代getitem魔法方法
3.iter和getitem都没有找到则返回错误
迭代器的意义:(引用‘樱雨楼’文章的观点)
在很多讨论 Python 迭代器的书籍与文章中,我看到这样两种观点:**1. 迭代器是为了节约数据结构所产生的内存;****2. 遍历迭代器效率更高。**
这两点论断都是很不准确的:首先,除了某些不定义在数据结构上的迭代器(如文件句柄,itertools 模块的 count、cycle 等无限迭代器等),其他迭代器都定义在某种数据结构上,所以不存在节约内存的优势;其次,由于迭代器是一种高度泛化的实现,其需要在每一次迭代器移动时都做一些额外工作(如 Python 需要不断检测迭代器是否耗尽,并进行异常监测;C++ 的 deque 容器需要对其在堆上用于存储的多段不连续内存进行衔接等),故遍历迭代器的效率一定低于或几乎接近于直接遍历容器,而不太可能高于直接遍历原容器。
综上所述,迭代器存在的意义,不是为了空间换时间,也不是为了时间换空间,而是一种适配器(Adapter)。迭代器的存在,使得我们可以使用同样的 for 语句去遍历各种容器,或是像 C++ 的 algorithm 模块所示的那样,使用同样的接口去处理各种容器。
这些容器可以是一个连续内存的数组或列表,或是一个多段连续内存的 deque,甚至是一个完全不连续内存的链表或是哈希表等等,我们完全不需要关注迭代器对于不同的容器究竟是怎么取得数据的。
生成器
生成器:函数中只要有yield,这个函数就会变成生成器。每次运行到yield的时候,函数会暂停,并且保存当前的运行状态,返回返回当前的数值,并在下一次执行next方法的时候,又从当前位置继续往下走。
应用场景:当不需要返回所有元素和元素占用很大内存时考虑生成器
- 协程
- 文件读取
- 需要迭代的场景

浙公网安备 33010602011771号