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方法的时候,又从当前位置继续往下走。

应用场景:当不需要返回所有元素和元素占用很大内存时考虑生成器

  1. 协程
  2. 文件读取
  3. 需要迭代的场景
posted @ 2019-10-09 22:57  小夏02  阅读(78)  评论(0)    收藏  举报