一、迭代器 – Iterator
迭代器可简单理解为一个可记住遍历位置的对象。每一次迭代都会进行业务运算返回一个值,数据只有在需要的时候去拉取的,而不是提前准备好,极大节省内存空间。
1. 迭代判别
首先要区分可迭代对象和迭代器(当然迭代器也属于可迭代对象),判别方式有两种:
方法一:使用isinstance() 函数来判断一个对象是否是一个已知的类型
from collections.abc import Iterable, Iterator
I = (i for i in range(10)) #迭代器
print(dir(I))
print(isinstance(I, Iterable)) #True
print(isinstance(I, Iterator)) #True
L = [i for i in range(10)] #列表
print(dir(L))
print(isinstance(L, Iterable)) #True
print(isinstance(L, Iterator)) #False
方法二:使用dir()函数查看对象的属性列表,如果只有__iter__()函数则是可迭代的,如果__iter__()和__next__()函数都有则是迭代器。
判断迭代器和可迭代对象的方案(野路子)
iter 可迭代的
iter && next 迭代器
2. 迭代解析
- getitem 可实现遍历,不可迭代,不是迭代器
class Person:
def __init__(self):
self.age = 1
def __getitem__(self, item):
self.age +=1
if self.age >=10:
raise StopIteration
return self.age
- iter 优先级高于__getItem__,可迭代,但对象不支持next(),不是迭代器
class Person:
def __init__(self):
self.age = 1
def __iter__(self):
self.age +=1
if self.age >=10:
raise StopIteration
return self.age
- next 迭代器,对象支持next()
class Person:
def __init__(self):
self.age = 1
def __iter__(self):
return self
def __next__(self):
self.age +=1
if self.age >=10:
raise StopIteration
return self.age
- StopIteration
迭代器直到遇到StopIteration中止; for 可以自行捕获该异常,并停止迭代
二、生成器 – Generator
可简单理解为生成迭代器的函数,绝大多数有借助yield实现;
生成器的本质就是迭代器,生成器函数通过yield将函数分解为多个部分,每一个部分都是迭代器中的__next__方法,生成器主要是延时操作或惰性操作。
- 遵循迭代器(iterator)协议,迭代器协议需要实现__iter__、next
- 接口 能过多次进入、多次返回,能够暂停函数体中代码的执行
yield 可记录函数当前执行位置,并返回一个值; 当函数再次调用时,会从上次调用位置继续执行; 迭代完成后,再次next()调用会抛出StopIteration异常;yield不要嵌套,会导致数据丢失;
def generator_example():
yield 1
yield 2
if __name__ == '__main__':
for e in generator_example():
print (e)
# output 1 2
generator function 产生的generator与普通的function有什么区别呢
1)function每次都是从第一行开始运行,而generator从上一次yield开始的地方运行
2)function调用一次返回一个(一组)值,而generator可以多次返回
3)function可以被无数次重复调用,而一个generator实例在yield最后一个值 或者return之后就不能继续调用了
References: https://blog.csdn.net/zhong_jay/article/details/91799459