迭代器有了__next__为什么还要__iter__
来源:互联网 发布:sql格式化日期 编辑:程序博客网 时间:2024/06/09 21:22
最近看CloseableQueue实现时遇到一个很基础却一直没想的问题。
Python的迭代器中为什么需要实现两个魔法方法?
其实咋一看起作用的不就是__next__方法嘛,__iter__在打酱油?
我知道for in循环是靠__iter__协议机制实现的迭代,但干嘛不直接调next呢?为什么很多迭代器都要return self?
然后找了点相关资料,终于有了点理解。
概念
Python中关于迭代有两个概念,第一个是Iterable,第二个是Iterator,协议规定Iterable的__iter__方法会返回一个Iterator, Iterator的__next__方法(Python 2里是next)会返回下一个迭代对象,如果迭代结束则抛出StopIteration异常。
理解
怎么理解呢?也就是iterator才是被调用next返回下一个迭代对象的类,而iterable是不一定具备这样的能力的,iterable的协议内容是其能返回一个iterator。当然,iterator也必须要实现__iter__方法,返回自己,这是协议上的统一实现。
为什么要这样设计协议呢?
假设我们现在只留下next接口,任何循环迭代情况直接调用next()方法,如果遇到一个结构直接用next实现迭代数据或迭代器生成器都直接暴露的那可以,如果遇到一个用生成器实现迭代数据,而代码被设置在一个结构内部怎么办,我们就必须先通过结构内部的方法将生成器取到外面,然后由生成器逐渐取得外部数据。不然每次直接对这个结构调用next只会得到一堆生成器,这太傻了。
这样的话不如定义一个协议,让所有这种包含生成器情况的结构有一个公共方法__iter__,循环结构直接用这个结构取代真正的iterator,用这个__iter__自动取出内部的生成器再取得数据。这样的代码优雅又方便,这个包含数据的外部结构就是 iterable。这种协议在next实现的迭代器中,就直接返回self,这样就实现了接口的统一。
另外,__iter__接口还可以在返回迭代器之前对迭代器做一些处理,list,dic等数据结构可以重复遍历甚至并发遍历,它们在iter返回的是独立的迭代器,迭代过程互不影响,这也是__iter__这个接口的作用。当然,具体list如何返回独立迭代器代码没看过。也只是看到别人这么提到。在自己的代码中如何应用这个特性暂不清楚。
- 迭代器有了__next__为什么还要__iter__
- iterator, __iter__, __next__
- 有了进程为什么还要线程?
- 有了gpio_request为什么还要gpio_request_one
- 有了百度为什么还要读书
- python之__iter__函数与__next__函数
- 有了malloc/free为什么还要new/delete
- 有了malloc/free为什么还要new/delete ?
- 有了malloc/free为什么还要new/delete
- 有了malloc/free为什么还要new/delete?
- 有了OpenMP,MPI,为什么还要MapReduce?
- 有了malloc/free为什么还要new/delete?
- 有了malloc/free为什么还要new/delete?
- 有了CPL和DPL,为什么还要RPL
- 有了"数据库"为什么还要用"xml" ?
- 有了malloc/free为什么还要new/delete?
- 有了malloc/free为什么还要new/delete ?
- 有了malloc/free为什么还要new/delete?
- java list键值对解析
- ue4-骨骼动画相关(换装、重定向、曲线、变形)
- Java的构造代码块和静态代码块的区别
- x265代码阅读:码率控制(一)
- 复习JQ (10)
- 迭代器有了__next__为什么还要__iter__
- js利用script标签跨域请求
- Java 构造器
- Innodb中的事务隔离级别和锁的关系
- HAUTOJ 1268: 小天使改名
- 百度Map的基本使用和定位
- HDU___1000
- 去重排序
- CentOS 7 安装教程、硬盘分区、LVM、网络配置、软件源配