迭代器---生成器
迭代器---生成器
一、迭代器
1.迭代
含义: 通过迭代器不断取出可迭代对象中的下一个元素的过程
可迭代对象: 能被迭代的对象
方法:
判断迭代器是否是可迭代对象 : isinstance(对象, Iterable)
判断迭代器对象是否是迭代器 : isinstance(对象, Iterator)
2.迭代器
含义: 迭代的访问 可迭代对象中的下一个元素
导入模块 : from collections import Iterator
应用场景 : 用户只需要关心如何使用迭代器访问数据 而不需要关键数据该如何访问
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang from collections import Iterator from collections import Iterable # 1.迭代器 - 记录每次访问的位置信息的对象 便于下一次访问(当访问完成后会自动执行下一个位置) # 2.应用场景 不同可迭代对象有不同的访问方式 每一种可迭代对象都会提供一个迭代器 # 用户只需要用迭代器取出 下一个元素 即可,而不应具体范文细节 - 解耦合 # 3.自定义迭代器类型 实现__next__方法 class MyRangeIter(object): """迭代器类""" def __init__(self, n): self.n = n self.i = 0 def __next__(self): """实现迭代器类型 一定要实现该方法 目的:返回用户需要的下一个元素的值""" if self.i < self.n: self.i += 1 return self.i else: # 停止 迭代 当迭代器完成的时候 抛出这个异常' raise StopIteration def __iter__(self): """python规定迭代器也必学是可迭代对象 因此使用此方法""" return self class MyRange(object): """可迭代类型""" def __init__(self, n): self.n = n def __iter__(self): """实现一个可迭代类型 一定要实现本方法 目的"返回一个迭代器""" return MyRangeIter(self.n) # 4.判断迭代器类型 # print("判断迭代器类型",isinstance(MyRangeIter(5), Iterator)) # print("判断迭代器是否是可迭代对象",isinstance(MyRangeIter(5), Iterable)) # print("判断迭代器对象是否是迭代器",isinstance(MyRange(5), Iterator)) for i in MyRange(5): print(i) input(":")
二、生成器
1.生成器表达式
列表推导式 [ ] ---> ()
优点 : 节约资源,不占用大量空间, 在用户需要访问数据的时候 , 才延迟产生
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
a = (x +1 for x in range(5)) print(a.__next__()) print(a.__next__()) #### 打印结果 #### 1 2
2.生成器函数
定义 :
1.执行到yield会暂停当前代码执行 将后面的值返回到调用生成器代码的地方
2 .当前生成器代码再次执行时 直接从上次暂停的地方继续往下执行
send关键字:
如果第一次启动生成器使用send方法,那么参数只能传入None,一般第一次启动生成器使用next函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang def myrange(n): start = 0 while start < n : number = yield start print("接收道路数据%s" % number) start += 1 if __name__ == '__main__': gen = myrange(3) # 生产器支持操作-next函数 迭代器支持的操作 i = next(gen) print(i) # 生成器支持操作-send方法 特有 i = gen.send(None) print(i) # 对比 两种执行生成器的方式的异同 # 1 同 : 都可以执行生成器代码 并且获取到一个值 # 2 异: next不可以发送数据; send可以发送数据; # 第一次调用时send(None),next没有这个要求
return 和 yelid 区别:
yield: 每次启动生成器都会返回一个值,多次启动可以返回多个值,也就是yield可以返回多个值
return: 只能返回一次值,代码执行到return语句就停止迭代
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang def myrange(n): start = 0 while start < n: yield start # return "呵呵" print("------") start += 1 # 生成器函数不是普通函数 调用函数()产生print(next(gen))生成器对象 # 执行生成器函数的代码 需要调用next(生成器对象) gen = myrange(5) i = next(gen) print(i) try: print(next(gen)) except Exception as e: # 如果需要获取到 生成器最终return的值 需要捕获异常 print("接收的异常数据: %s" % e) # print(next(gen)) # print(next(gen)) # print(next(gen)) # print(next(gen))