Python之迭代器与生成器
一、迭代器
1、可迭代对象:可以直接作用于for循环的对象统称为可迭代对象,即Iterable。
常见迭代对象:str、list、tuple、dict、set、range
检测迭代对象的方法:
1)、方法一:dir(被测对象)-- 如果含有__iter__ ,那这个对象就叫做可迭代对象.
#返回True表示是可可迭代对象,False则不是 str1 = 'hello' print('__iter__' in dir(str1)) #True num = 2018 print('__iter__' in dir(num)) #False
2)、方法二:测试它是迭代器还是可迭代对象,使用isinstance()方法
#检测可迭代对象与迭代器的方法 lis = [1,2,3] from collections import Iterable #Iterable 可迭代对象 from collections import Iterator #Iterator 迭代器 print(isinstance(lis,Iterable)) #True print(isinstance(lis,Iterator)) #False # isinstance() 是python内建函数,返回对象是否是类或其子类的实例。若是返回True,反之返回False。
可迭代对象转换迭代器:
#可迭代对象.__iter__() ---> 迭代器 iterator--遵循迭代器协议 str1 = 'ABC' strIter = str1.__iter__() #转化迭代器 print(str) #<class 'str'> print(strIter) #<str_iterator object at 0x000002C1A1629B38> print(strIter.__next__()) #A
2、迭代器:一个可以记住遍历的位置的对象,即Iterator
迭代器包含:文件句柄
2.1、迭代器的取值
#取值方式 使用__next__() s1 = 'ABCD' s3 = s1.__iter__() print(s3.__next__()) print(s3.__next__()) print(s3.__next__()) print(s3.__next__()) print('__iter__' in dir(s1)) #True print('__iter__' in dir(s3)) #True print('__next__' in dir(s1)) #False print('__next__' in dir(s3)) #True #输出结果 A B C D True True False True #只含有__iter__方法的数据是可迭代对象 #含有__iter__方法,并且含有__next__方法的数据是迭代器
2.2、迭代器的意义
1、迭代器节省内存.
2、迭代器惰性机制.
3、迭代器不能反复,一直向下执行.
2.3、for循环的机制
1)、内部含有__iter__方法,它会将可迭代对象先转化成迭代器,然后在调用__next__方法.
2)、它有异常处理的方法.
#实例1 for循环完美实现迭代 for i in [1,2,3]: print(i, end=' ') #1 2 3 #实例2 while循环需要异常处理语句才能实现迭代 l = [1,2,3] l_iter = l.__iter__() while True: try: print(l_iter.__next__(), end=' ') #1 2 3 except StopIteration: break
二、生成器
1.1、定义:使用了 yield 的函数被称为生成器,即Generator,本质就是迭代器,即自己用python代码写的迭代器.
1.2、生成方式:
1)、可以用生成器函数.
2)、可以用各种推导式构建迭代器.
3)、可以通过数据转化.
#普通函数 def func(): return 222 ret = func() print(ret) #111 #生成器函数--生成器 def gener(): yield 111 yield 222 g = gener() print(g) #<generator object gener at 0x000001C8E10A43B8> print(g.__next__()) #111 print(g.__next__()) #222 #return与yield的区别 #return 返回给调用者值,并结束此函数. #yiled 返回给调用者值,并将指针停留着当前位置.
1.3、send函数
1)、send 和 next 功能一样
2)、给上一个yiled 整体发送一个值
注:send不能给第一个和最后一个yield发送值(但可以使用send(None)将值返回),只能使用next
def gener(): yield 111 count = yield 222 print('-->',count) yield 333 yield 444 g = gener() print(g.__next__()) print(g.send('AAA')) print(g.send('BBB')) #count--> BBB print(g.send('last')) #输出结果 111 222 --> BBB 333 444