迭代对象、迭代器、生成器浅析

这三者都是迭代对象,可通过for循环逐个获取对象元素。生成器基本不占用内存无论有多大数据量,但是只能使用一次(也可以通过一些途径使用多次)。

迭代对象 iterables

能一次返回一个元素的对象,主要用于for循环。

基本上python的所有容器(container)都是可迭代的,比如有序容器list, str, tuple,set 和无序容器dict, file,还有collections模块提供的几个亮瞎眼的容器namedtuple、OrderedDict、Counter、defaultdict、deque、ChainMap、UserDict、UserList、UserString。一般情况下,要扩展内置类型的功能需要通过子类化来实现,但轮子已被前辈造好,不仅性能好,而且使得代码更加简洁pythonic。

例子,Counter()用于统计元素出现的个数,是字典builtins.dict的子类。

通常做法:

s="afmldskmfl"
occurrences = {}
for _,e in enumerate(s):occurrences1[e]=occurrences1.get(e,0)+1#返回{';': 1, 'a': 3, 'd': 1, 'f': 1, 'k': 1, 'l': 1, 's': 3}

pothonic写法:

occurrences = Counter(s)#返回Counter({';': 1, 'a': 3, 'd': 1, 'f': 1, 'k': 1, 'l': 1, 's': 3})
occurrences.most_common(2)#返回[('s', 3), ('a', 3)]

Counter()除了继承dict的方法,自己又实现了三个,elements()、most_common()、subtract()。

可迭代对象本质上是实现了魔法方法__iter__()__getitem__(),该方法可以看做是所有迭代对象都要遵循的一个协议。所以,除了python内置的迭代对象,我们也可以在自己定义的class里通过重载__iter__()来获得可迭代性。

大多容器是可迭代对象,只有少数是迭代器。比如list就是个迭代对象,但如果调用了魔法方法__iter__(),则会变成一个迭代器。例子如下。

x = [1,2,3]
isinstance(x, clc.abc.Iterable)#返回True
isinstance(x, clc.abc.Iterator)#返回False
x1 = iter(x)#或者用x1 = x.__iter__()
isinstance(x1, clc.abc.Iterator)#返回True

迭代器 iterator

迭代器必定是可迭代对象。

所以迭代器是可迭代对象的子类,必须遵循迭代协议,即有方法__iter__(),同时自己也有方法__next__()

其实,__next__()基本是实现了迭代对象的for循环操作,但区别是next会耗尽迭代器,当到达元素末尾之后再调用next会出现StopIteration异常,同时也是一次性的,耗尽之后再没法使用。

而for循环接收迭代对象的StopIteration异常并以此为break条件,同时,for中使用迭代对象就完全可以工作了,没必要把迭代器放在for循环里,多此一举,而且最重要的是迭代对象不会耗尽。

一个迭代对象可通过魔法方法__iter__()转变为一个迭代器,即iterator=iterable.__iter__()iterator=iter(iterable)

自己实现一个计算Fibonacci数列的迭代器:

import collections as clcclass Fibonacci(object):def __init__(self, n=10):self.a = 0self.b = 1self.n = ndef __iter__(self):"""若存在此方法,python解释器会把实例化的对象当做迭代对象"""return selfdef __next__(self):"""若存在此方法,python解释器会把实例化的对象当做迭代器"""if self.n == 0:raise StopIterationself.a, self.b = self.b, self.a+self.bself.n -= 1return self.bif __name__ == "__main__":z = Fibonacci(5)#实例化对象print(isinstance(z, clc.abc.Iterable))#输出Trueprint(isinstance(z, clc.abc.Iterator))#输出Trueprint(next(z))#输出1print(z.__next__())#输出2for f in z:print(f)#输出3,5,8

虽然这不是实现Fibonacci数列很Pythonic的方式,但是可以了解迭代器的工作原理。

迭代器可以说是个鸡肋般的存在,远不如迭代对象用途广泛,近不如生成器那样高效简洁—-鲁迅。但他是生成器的基石。

生成器 generator

为什么叫生成器呢?其实是一种生成的迭代器(generate iterators),故也称generator iterators,简称generators,即生成器。

一个自定义生成器最显著的特征是yield语句。当解释器看到存在yield语句时,便知道这是个生成器定义。

普通函数用return返回,而生成器用yield作为名义上的返回。

当调用普通函数时,return语句前的所有代码全部被执行,然后返回return后的值;如果返回的是一个list,则所有值都会写入这个list存在于内存中。
当调用生成器时,每次调用会返回yield后面的值并把当前位置记住,下次再调用时就从这个位置开始。所以,yield语句可以写在一个无限循环里而不用提供终止函数的条件!因为每次返回一个值,所以基本不会占用内存,无论数据有多少。

其实,yield实现的功能与__iter__()+__next__()是一样的。很显然,要实现同一个功能,定义一个类比直接用一个普通函数(plain function)更复杂。而yield正好可以通过一个简单函数实现一个类才能干的事。

用生成器实现Fibonacci数列。

def fibonacci(n):a, b = 0, 1while True:if n == 0:raise StopIterationyield ba, b = b, a+bn -= 1
if __name__ == "__main__":z = fibonacci(5)#调用函数,将生成器赋给变量zprint(isinstance(z, clc.abc.Iterable))#输出Trueprint(isinstance(z, clc.abc.Iterator))#输出Trueprint(next(z))#输出1print(z.__next__())#输出2for f in z:print(f)#输出3,5,8

python标准库里自带的生成器有range()dict.items()zip()map()open等,功能都很强度,尤其是zip对于一次性迭代多个迭代对象时更是效率惊人,可参照我的前一篇文章8行代码实现ui文件到py文件转换。

总结

从范围来讲,迭代对象>迭代器>生成器

网上的一张图片很清晰地解释了三者之间的关系。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(内容同步更新到微信公众号python数学物理,微信号python_math_physics

迭代对象、迭代器、生成器浅析相关推荐

  1. python可迭代对象 迭代器生成器_Python可迭代对象、迭代器和生成器

    8.1 可迭代对象(Iterable) 大部分对象都是可迭代,只要实现了__iter__方法的对象就是可迭代的. __iter__方法会返回迭代器(iterator)本身,例如: >>&g ...

  2. python中迭代器和可迭代对象的区别_Python 可迭代对象迭代器生成器的区别

    生成器是一种特殊的迭代器,生成器自动实现了"迭代器协议"(即__iter__和next方法),不需要再手动实现两方法. 首先从字面意思来解释Iterable和Iterator的区别 ...

  3. Python要想学得好,【容器/可迭代对象/迭代器/生成器】少不了,稳扎稳打学Python!

    在刚开始学Python的时候,是不是经常会听到大佬们在讲容器.可迭代对象.迭代器.生成器.列表/集合/字典推导式等等众多概念,其实这不是大佬们没事就搁那扯专业术语来装B,而是这些东西都得要明白的,光知 ...

  4. 【Python】【容器 | 迭代对象 | 迭代器 | 生成器 | 生成器表达式 | 协程 | 期物 | 任务】...

    Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyn ...

  5. 5.Python基础语法(函数/条件控制/循环语句/可迭代对象/迭代器/生成器/对象赋值/浅复制/深复制)

    5.1 函数 在中学数学中我们知道y=f(x)代表着函数,x是自变量,y是函数f(x)的值.在程序中,自变量(x)可以代表任意的数据类型,可以是字符串.列表.字典.对象,可以是我们认为的任何东西. 示 ...

  6. 迭代器、可迭代对象与生成器

    Iterator 与 gerater的作用是优化内存,当处理大文件,大数据的时候可以使用. 1. 对大列表进行优化 2. 大文件的优化 一.基本概念 迭代器: 一种数据类型,用来处理大数据 可迭代对象 ...

  7. python手写一个迭代器_搞清楚 Python 的迭代器、可迭代对象、生成器

    很多伙伴对 Python 的迭代器.可迭代对象.生成器这几个概念有点搞不清楚,我来说说我的理解,希望对需要的朋友有所帮助. 1 迭代器协议 迭代器协议是核心,搞懂了这个,上面的几个概念也就很好理解了. ...

  8. python 函数可以作为容器对象的元素_11.Python初窥门径(函数名,可迭代对象,迭代器)...

    python(函数名,可迭代对象,迭代器) 一.默认参数的坑 # 比较特殊,正常来说临时空间执行结束后应该删除,但在这里不是. def func(a,l=[]): l.append(a) return ...

  9. Python练习 | Python 可迭代对象 迭代器

    博主github:https://github.com/MichaelBeechan 博主CSDN:https://blog.csdn.net/u011344545 在使用Python的过程中,很容易 ...

最新文章

  1. 创建型设计模式对比总结 设计模式(八)
  2. 接口(Interface)的深入理解
  3. LCD编程_LCD控制器
  4. java普通类跳转到jsp_JSP跳转到Servlet的两种配置
  5. 【树莓派学习笔记】四、OpenCV的安装与卸载
  6. 分布式一致性算法2PC和3PC
  7. select 下拉框的选中项的change事件
  8. @RequestParam
  9. LVS负载均衡中arp_ignore和arp_annonuce参数配置
  10. Mathcad绘制三维散点图
  11. 如何通过安全的网络防御XcodeGhost?
  12. 使用CSS实现国际象棋棋盘
  13. c语言while函数作用,c语言while(c语言while循环用法)
  14. Eclipse快捷方式无法在桌面上打开
  15. 苹果手机上网速度慢_人群中手机网速不好,怎么办?
  16. excel打不开_2016EXCEL表格打不开,提示格式与文件扩展名指定的格式不一致,这么做!...
  17. 第十一届中国云计算标准和应用大会 | 华云数据成为全国信标委云计算标准工作组云迁移专题组副组长单位副组长单位
  18. 外汇天眼:Apple与MetaQuotes之争!谁是下一个Apple?谁会成下一个MT4/5?
  19. 你写的JSP就是JSP么?
  20. 瞧一瞧~看一看~MyCat架构剖析免费不要钱!(下)

热门文章

  1. 2014 android全球用户,IDC发布数据:2014年Q2全球智能手机出货量超过3亿部,iOS与Android统治了其中96.4%的市场...
  2. 认识设备树(二)——设备树文件的格式
  3. python hook微信_基于hook的python机器人,彻底取代itchat
  4. k8s部署有状态(StatefulSet)zk-kafka集群
  5. 宝塔安装sqlserver_windows 宝塔安装sql_server 2008,php链接配置流程
  6. 2020 下半年,写给自己
  7. cad尺寸标注快捷键_Auto CAD 尺寸标注快捷键
  8. 7-8 古老的汉诺塔 (20分)
  9. 旧手机升级android9,给力!一加两款旧旗舰获得安卓9.0升级:新增手势功能
  10. 【Excel】单元格输入换行符、替换换行符