迭代器和生成器
Generator:生成器
Iterator:迭代器
Iterable:可迭代对象
可迭代对象
能够进行迭代逐一返回其成员项的对象称为可迭代对象。可迭代对象例子包括
- 所有序列类型:如list、str、和tuple
- 非序列类型:dict、set、文件对象
- 实现了__iter__()方法的任意对象(可迭代协议)
- 实现了序列语义的__getitem__()方法的任意对象
迭代协议和迭代器协议
迭代协议:
对象定义了一个__iter__方法的,那么这个对象就实现了迭代协议,__iter__方法的返回值必须是一个迭代器
迭代器协议:
迭代器协议由一个__iter__方法和__next__方法共同构成。实现了这两个方法的对象就实现了迭代器协议
- 对象实现了迭代协议的对象
- 对象实现了__next__方法,__next__方法在迭代完成数据后,会抛出StopIteration的错误信息
迭代器(Iterator)
定义表达式:tup=iter([23,32,44,54])
当迭代器中的数据,全部迭代完毕之后,再次进行迭代操作会报错,一次next只会返回一条数据
- 实现了迭代器协议的对象,就是一个迭代器
- 所有的可迭代对象,都可以通过内置函数iter()转换为迭代器
- 迭代器对象能够使用内置函数next()进行迭代操作
- 所有迭代器都是可迭代对象,因为迭代器协议包含了迭代协议
生成器(Generator):
- 当函数中有yield时,这个函数就是生成器函数,在调用函数的时候会返回一个生成器对象,调用不函数不会执行函数内部代码
- 只有生成器进行迭代操作的时候,才会执行生成器函数的代码
- 使用next()方法,就可以启动生成器函数执行,调用一次next()就执行一次
优点:节约内存
生成器表达式:
1、tup = (i for i in range(10)),tup返回的是一个生成器对象
2、用函数定义生成器
def func():
print("---------start---------------")
for i in range(100):
yield i
print('---------{}---------'.format(i))
res = func()
第一次迭代的时候执行到yield就会暂停,然后返回i的数据,下次执行生成器迭代 的时候,当遇到yield时会再次暂停
res1 = next(res)
res2 = next(res)
输出:
0
1
生成器函数调用时不会执行,直接返回一个生成器对象
生成器进行迭代操作的时候,才会执行生成器函数中的代码
使用next进行迭代,就可以启动生成器函数执行
生成器和迭代器的区别:
1、生成器和迭代器的迭代数据都使用内置函数next();
2、生成器有close()方法,来关闭生成器,关闭生成器后,不能在进行数据迭代
3、生成器可以用send()方法 和生成器内部数据进行交互,send方法必须在使用了next方法后,才能使用,或者在第一次使用send()的时候跟send()方法传一个None
4、生成器,可以使用throw()方法,往生成器内部主动抛出异常
生成器next()方法和send()方法的运用
两者区别:
实际上next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。因此,我们可以看做next(g) 和 g.send(None) 作用是一样的。
g=fun() #创建生成器对象,不会立即执行
next(g) #第一次执行next()方法时启动生成器,代码运行到第7行,然后跳出生成器
print(g.send("牛呀")) #执行send()方法后再次进入生成器函数,运行yield后面的代码,然后重新运行到yield语句
备注:需要先执行next()方法后,才能执行send方法,否则会报错
输出:
a的值:牛呀
1