可迭代对象

什么是可迭代对象?顾名思义就是可以迭代的一个对象,再通俗点就是可以被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可迭代对象、迭代器和生成器相关推荐

  1. python文件对象是可以迭代的_详解python可迭代对象、迭代器和生成器

    可迭代对象 什么是可迭代对象?顾名思义就是可以迭代的一个对象,再通俗点就是可以被for循环遍历的对象,如常用的list.str等数据类型.我们可以使用isinstance来判断这个数据是否是可迭代对象 ...

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

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

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

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

  4. python中嵌套函数的应用实例-实例详解python函数的对象、函数嵌套、名称空间和作用域...

    函数的对象 python中一切皆对象 函数对象的四大功能 引用 def f1(): print("from f1") f1() #调用函数 print(f1) print(&quo ...

  5. python的装饰器迭代器与生成器_详解python中的生成器、迭代器、闭包、装饰器

    迭代是访问集合元素的一种方式.迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 1|1可迭代对象 以直接作用于 for ...

  6. python列表拆包_详解python 拆包可迭代数据如tuple, list

    详解python 拆包可迭代数据如tuple, list 拆包是指将一个结构中的数据拆分为多个单独变量中. 以元组为例: >>> a = ('windows', 10, 25.1, ...

  7. 详解 Python 源码之对象机制

    在Python中,对象就是在堆上申请的结构体,对象不能是被静态初始化的,并且也不能是在栈空间上生存的.唯一的例外就是类型对象(type object),Python中所有的类型对象都是被静态初始化的. ...

  8. python中可迭代对象拆包时、怎么赋值给占位符_python3-数据结构和算法 » 1.2 解压可迭代对象赋值给多个变量...

    1.2 解压可迭代对象赋值给多个变量 问题 如果一个可迭代对象的元素个数超过变量个数时,会抛出一个 ValueError . 那么怎样才能从这个可迭代对象中解压出 N 个元素出来? 解决方案 Pyth ...

  9. python可迭代对象,迭代器,生成器

    容器是一系列元素的集合,str.list.set.dict.file.sockets对象都可以看作是容器,容器都可以被迭代(用在for,while等语句中),因此他们被称为可迭代对象. 可迭代对象实现 ...

最新文章

  1. Okhttp----缓存的加入方式----附完整demo
  2. 2018-2019-1 20165226 《信息安全系统设计基础》第4周学习总结
  3. 面向 Photoshop 的英特尔® Texture Works 插件
  4. VC中获取窗口句柄的各种方法
  5. cent 8.0 安装tomcat 9.0_nginx+tomcat会话保持方案探讨
  6. SAP Data Intelligence Modeler里的Kafka Producer和Kafka Consumer
  7. flutter英语怎么说_美国人天天说的英语:“你搞反了”英语怎么说?
  8. cte公用表表达式_CTE SQL删除; 在SQL Server中删除具有公用表表达式的数据时的注意事项
  9. 全新的 Discuz! Q 来了!
  10. 大数据的搜索引擎——Elasticsearch
  11. JSON.parse()函数处理json格式字符串方法
  12. linux下cmake使用教程,超详细的cmake教程
  13. Excel表格快速转PDF
  14. 电脑控制android手机神器,scrcpy
  15. 计算机设备管理器更新驱动器,怎么利用设备管理器更新显卡驱动 - 驱动管家
  16. 智能家居--domoticz配置和风天气 HTTP/HTTPS poller 的使用以及domoticz_updateDevice的介绍
  17. R和RStudio安装包下载
  18. dede taglist模板中调用自定义字段
  19. 打造高性能高可靠的 Ceph 块存储系统
  20. jnlp文件打开方式(jnlp文件打开方式Java)

热门文章

  1. opencv3.4.3的DNN模块调用bvlc_googlenet.caffemodel实现图像分类
  2. os.path.join()函数用法
  3. 机器学习算法(5)——决策树(ID3、C4.5、CART)
  4. Git Branch Mode(分支模式)
  5. CSS Scrollbar (滚动条)
  6. 字符串字母大小写转换
  7. python turtle用法_Python初学者Turtle库简介
  8. shell 如何避免误删目录
  9. python发红包实现
  10. SoftWater——SDN+UnderWater系列论文一