Python生成器和迭代器
作者:王大为
时间:2016-10-24 11:00
一、生成器generator
分为以下两种:
1、列表生成器,形如:( i * i for i in range(10))
2、函数生成器,yield关键字
1、列表生成器
1.1、第一种情况(基本)
代码code:
结果result:
1.2、第二种情况(if判断)
代码code:
结果result:
1.3、第三种情况(循环for嵌套)
代码code:
结果result:
1.4、第四种情况(使用字典)
代码code:
结果result:
2、函数生成器
和函数一起使用:可以使函数中断并保存函数的中断状态,yield关键字,可以减少程序的阻塞
2.1、next()方法
yield 对应值:调用__next__()方法时返回的值
例如yield a,则__next__()方法时返回a
yield + 后面的值:整个表达式为none(send函数传递的就是整个表达式的值进去)
1、例如c = yield a,则c为None
2、例如c = yield a,并且send('hello'),则c为'hello'
代码code:
def fib(s):
n, a, b = 0, 0, 1
while n < s:
print('-------')
yield b
print('hello')
a, b = b, a + b
n += 1
return 'out of range'
fib_gen = fib(5)
a = fib_gen.__next__()
print(a)
结果result:
2.2、异常StopIteration
异常的信息value就是函数生成器的return返回值信息
代码code:
def fib(s):
n, a, b = 0, 0, 1
while n < s:
print('-------')
yield b
a, b = b, a + b
n += 1
return 'out of range'
fib_gen = fib(5)
for i in range(6):
try:
print(fib_gen.__next__())
except StopIteration as e:
print(e.value)
结果result:
2.3、send()方法
生成器的send方法可以传递整个表达式(yield a)的值
需要注意的是:生成器必须被运行后才可以使用send方法,表现为必须首先调用__next__方法,然后才可以使用send方法
原因:就是python中,在执行fib_gen = fib(5),并没有进入函数内部执行,这个时候,只是把fib_gen定义为了一个生成器;只有等fib_gen被执行了以后,才会启动生成器;所以在python代码里面,send比yield还早,这是有问题的需要首先添加fib_gen.__next__()方法
2.3.1、直接调用send方法
代码code:
def fib(s):
n, a, b = 0, 0, 1
while n < s:
a = yield b
print(a)
n += 1
return 'out of range'
fib_gen = fib(5)
fib_gen.send('hello')
结果result:
2.3.2、首先next()启动生成器,然后调用send方法
代码code:
def fib(s):
n, a, b = 0, 0, 1
while n < s:
a = yield b
print(a)
n += 1
return 'out of range'
fib_gen = fib(5)
fib_gen.__next__()
fib_gen.send('hello')
结果result:
二、迭代器iterator
1、迭代器的组成分类
一类是集合数据类型,例如:list,tuple,dict,set,str等
一类是generator对象,包括列表生成器和带yield的generator function
2、可迭代对象
定义:凡是可作用于for循环的对象都是iterable类型,可迭代对象
判断:使用isinstance()函数判断是否是可迭代对象
代码code:
from collections import Iterable
a = isinstance([], Iterable)
b = isinstance((), Iterable)
c = isinstance('', Iterable)
d = isinstance({}, Iterable)
e = isinstance(12, Iterable)
print(a)
print(b)
print(c)
print(d)
print(e)
结果result:
3、迭代器
定义:凡是可作用于next()的对象都是iterator类型,迭代器
4、可迭代对象——>迭代器的转化,iter()内置函数,将iterable可迭代对象转化为iterator迭代器
代码code:
from collections import Iterator
a = isinstance([], Iterator)
b = isinstance(iter(()), Iterator)
print(a)
print(b)
结果result:
5、总结
生成器一定是迭代器,但是迭代器不一定是生成器(集合数据类型转化的迭代器)
可作用于for循环的对象是可迭代对象
可作用于next()的对象是迭代器
可迭代对象可以通过iter()函数转化为迭代器