详解python可迭代对象、迭代器和生成器
可迭代对象
什么是可迭代对象?顾名思义就是可以迭代的一个对象,再通俗点就是可以被for循环遍历的对象,如常用的list、str等数据类型。我们可以使用isinstance来判断这个数据是否是可迭代对象,在此要先从Iterable包中导入模块collections。
from collections import Iterable
a = 1 #int
b= [1,2,3] #list
c= "abc" #str
d = {1,2,3} #set
e = (1,2,3) #tuple
f = {1:'a',2:'b'}#dict
g = open('test.py')
print (isinstance(a,Iterable))
print (isinstance(b,Iterable))
print (isinstance(c,Iterable))
print (isinstance(d,Iterable))
print (isinstance(e,Iterable))
print (isinstance(f,Iterable))
print (isinstance(g,Iterable))
False
True
True
True
True
True
True
可以看出除了像int、float、complex这种基本类型外,其他的数据类型都是属于可迭代对象,包括文件对象。他们之所以被python内部认为是一种可迭代对象,是因为他们都具有__iter__方法,用hasattr可以看出来。
a = 1 #int
b= [1,2,3] #list
c= "abc" #str
d = {1,2,3} #set
e = (1,2,3) #tuple
f = {1:'a',2:'b'}#dict
g = open('test.py')
print (hasattr(a,'__iter__'))
print (hasattr(b,'__iter__'))
print (hasattr(c,'__iter__'))
print (hasattr(d,'__iter__'))
print (hasattr(e,'__iter__'))
print (hasattr(f,'__iter__'))
print (hasattr(g,'__iter__'))
False
True
True
True
True
True
True
靠__iter__这个方法我们就可以自己创造一个可迭代对象,如下所示:
from collections import Iterable
class A():def __init__(self):passdef __iter__(self):pass
class B():def __init__(self):pass
a = A()
b = B()
print (isinstance(a,Iterable))
print (isinstance(b,Iterable))
True
False
上面代码可以看出来,在一个类中加入了__iter__这个方法,实例化的对象就会被python内部认为是一个可迭代的对象。
迭代器
上面介绍了什么是可迭代对象。那么什么是迭代器呢?迭代器跟可迭代对象又是什么关系呢?那么先解释第一问,迭代器对象是要求支持迭代器协议的对象,在Python中,支持迭代器协议就是实现对象的__iter__()和next()方法。其中__iter__()方法返回迭代器对象本身;next()方法返回容器的下一个元素,在结尾时引发StopIteration异常。事实上,我们可以用上述的方法来检测一下那些数据类型是不是属于迭代器。
from collections import Iterator
a = 1 #int
b= [1,2,3] #list
c= "abc" #str
d = {1,2,3} #set
e = (1,2,3) #tuple
f = {1:'a',2:'b'}#dict
g = open('test.py')
print (isinstance(a,Iterator))
print (isinstance(b,Iterator))
print (isinstance(c,Iterator))
print (isinstance(d,Iterator))
print (isinstance(e,Iterator))
print (isinstance(f,Iterator))
print (isinstance(g,Iterator))
False
False
False
False
False
False
True
结果显示除了文件对象,其他的数据类型都不是迭代器,上面说过,迭代器必须同时有__iter__和__next__方法,我们可以看看文件对象和列表,比较他们是否有__next__方法,依次验证。
print (hasattr(b,'__next__'))#list
print (hasattr(g,'__next__'))#文件对象
False
True
再讲一下可迭代对象和迭代器的区别,我们都知道在学习python时流行这么一句话“一切皆对象”,那么显然易见可迭代对象就包括了迭代器,之所以把把文件对象又叫做迭代器,是因为它多了一种__next__方法而已。
知道了上述所讲的内容后,我们就可以试着自己写一个迭代器,无非就是加入__iter__和__next__方法。
from collections import Iteratorclass A():def __init__(self,i):self.n = 0self.i = idef __iter__(self):return selfdef __next__(self):if self.i > self.n:var = self.iself.i -= 1return varelse:raise StopIteration()
a = A(5)
print (isinstance(a,Iterator))
for i in a:print (i)#True
#5
#4
#3
#2
#1
创建一个迭代器还可以使用python内置的函数iter和next,如下:
from collections import Iteratora = [1,2,3]
b = iter(a)
print (next(b))
print (isinstance(b,Iterator))
1
True
上述代码用iter将一个可迭代对象变成了一个迭代器,然后就可以使用迭代器的专用方法next来一个一个地取出数据。
for循环内部机制
a = [1,2,3]
for i in a:print(i)#1
#2
#3
为什么一个列表放在for循环里就可以很快地取出内部所有元素呢?正常来说,一个可迭代对象是不能直接从其中取出元素的,但放在for循环里就可以,这是因为在循环时,它会先自动调用__iter__方法将列表变成一个迭代器,然后这个迭代器再调用其__next__()方法。
生成器
首先我们需要知道的是生成器本质就是一个迭代器,它同样拥有__iter__和__next__两个方法。与迭代器不同的是,他可以产生延迟操作,既不会立即出现结果,而是在你需要的时候才产生。生成器通过生成器函数产生,生成器函数可以通过常规的def语句来定义,但是不用return返回,而是用yield一次返回一个结果,在每个结果之间挂起和继续它们的状态,来自动实现迭代协议。也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。
def A(n):print ("----生成器开始-----")i = 1while n != 0:print("开始循环第%d次"%i)yield nn -= 1print ("第%d循环结束"%i)i += 1print ("----生成器结束----")a = A(3)
print (a.__next__())
----生成器开始-----
开始循环第1次
5
可以看出,生成器函数直接调用并不会马上执行,只有用next方法才能开始执行,next一次,他会直到碰到yield就会马上结束,当再次写一个next方法时(如下所示),它会在yield后继续执行下去,直到碰到下一个yield才会停止。如果没有找到yield,就会报出异常。
----生成器开始-----
开始循环第1次
5
第1循环结束
开始循环第2次
4
上述代码如果next方法执行四次,就会报出StopIteration错误。如下所示:
Traceback (most recent call last):
----生成器开始-----
开始循环第1次File "D:/untitled/test.py", line 20, in <module>
3
第1循环结束
开始循环第2次
2
第2循环结束
开始循环第3次
1print (a.__next__())
第3循环结束
----生成器结束----
StopIteration
生成器中还有两个很重要的方法:send()和close()。
send(value):next()方法可以恢复生成器状态并继续执行,其实send()是除next()外另一个恢复生成器的方法。与next不同的是,它需要传入一个参数,一般传入None,即send(None)与next()是等效的。
close():这个方法用于关闭生成器,对关闭的生成器后再次调用next或send将抛出StopIteration异常。
转载于:https://www.cnblogs.com/longwhite/p/10397718.html
详解python可迭代对象、迭代器和生成器相关推荐
- python文件对象是可以迭代的_详解python可迭代对象、迭代器和生成器
可迭代对象 什么是可迭代对象?顾名思义就是可以迭代的一个对象,再通俗点就是可以被for循环遍历的对象,如常用的list.str等数据类型.我们可以使用isinstance来判断这个数据是否是可迭代对象 ...
- Python练习 | Python 可迭代对象 迭代器
博主github:https://github.com/MichaelBeechan 博主CSDN:https://blog.csdn.net/u011344545 在使用Python的过程中,很容易 ...
- python可迭代对象 迭代器生成器_Python可迭代对象、迭代器和生成器
8.1 可迭代对象(Iterable) 大部分对象都是可迭代,只要实现了__iter__方法的对象就是可迭代的. __iter__方法会返回迭代器(iterator)本身,例如: >>&g ...
- python中嵌套函数的应用实例-实例详解python函数的对象、函数嵌套、名称空间和作用域...
函数的对象 python中一切皆对象 函数对象的四大功能 引用 def f1(): print("from f1") f1() #调用函数 print(f1) print(&quo ...
- python的装饰器迭代器与生成器_详解python中的生成器、迭代器、闭包、装饰器
迭代是访问集合元素的一种方式.迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 1|1可迭代对象 以直接作用于 for ...
- python列表拆包_详解python 拆包可迭代数据如tuple, list
详解python 拆包可迭代数据如tuple, list 拆包是指将一个结构中的数据拆分为多个单独变量中. 以元组为例: >>> a = ('windows', 10, 25.1, ...
- 详解 Python 源码之对象机制
在Python中,对象就是在堆上申请的结构体,对象不能是被静态初始化的,并且也不能是在栈空间上生存的.唯一的例外就是类型对象(type object),Python中所有的类型对象都是被静态初始化的. ...
- python中可迭代对象拆包时、怎么赋值给占位符_python3-数据结构和算法 » 1.2 解压可迭代对象赋值给多个变量...
1.2 解压可迭代对象赋值给多个变量 问题 如果一个可迭代对象的元素个数超过变量个数时,会抛出一个 ValueError . 那么怎样才能从这个可迭代对象中解压出 N 个元素出来? 解决方案 Pyth ...
- python可迭代对象,迭代器,生成器
容器是一系列元素的集合,str.list.set.dict.file.sockets对象都可以看作是容器,容器都可以被迭代(用在for,while等语句中),因此他们被称为可迭代对象. 可迭代对象实现 ...
最新文章
- Okhttp----缓存的加入方式----附完整demo
- 2018-2019-1 20165226 《信息安全系统设计基础》第4周学习总结
- 面向 Photoshop 的英特尔® Texture Works 插件
- VC中获取窗口句柄的各种方法
- cent 8.0 安装tomcat 9.0_nginx+tomcat会话保持方案探讨
- SAP Data Intelligence Modeler里的Kafka Producer和Kafka Consumer
- flutter英语怎么说_美国人天天说的英语:“你搞反了”英语怎么说?
- cte公用表表达式_CTE SQL删除; 在SQL Server中删除具有公用表表达式的数据时的注意事项
- 全新的 Discuz! Q 来了!
- 大数据的搜索引擎——Elasticsearch
- JSON.parse()函数处理json格式字符串方法
- linux下cmake使用教程,超详细的cmake教程
- Excel表格快速转PDF
- 电脑控制android手机神器,scrcpy
- 计算机设备管理器更新驱动器,怎么利用设备管理器更新显卡驱动 - 驱动管家
- 智能家居--domoticz配置和风天气 HTTP/HTTPS poller 的使用以及domoticz_updateDevice的介绍
- R和RStudio安装包下载
- dede taglist模板中调用自定义字段
- 打造高性能高可靠的 Ceph 块存储系统
- jnlp文件打开方式(jnlp文件打开方式Java)
热门文章
- opencv3.4.3的DNN模块调用bvlc_googlenet.caffemodel实现图像分类
- os.path.join()函数用法
- 机器学习算法(5)——决策树(ID3、C4.5、CART)
- Git Branch Mode(分支模式)
- CSS Scrollbar (滚动条)
- 字符串字母大小写转换
- python turtle用法_Python初学者Turtle库简介
- shell 如何避免误删目录
- python发红包实现
- SoftWater——SDN+UnderWater系列论文一