Python迭代器和生成器
一、迭代器
现在已知的可迭代对象:str list tuple dict set range和文件句柄。
但是,什么是可迭代对象?可迭代对象的测量方法。
方法一: dir(被测对象) 如果 他含有__iter__ ,那这个对象就叫做可迭代对象.
下面字符串S就是可迭代对象:
s= 'abcdef'
print('__iter__' in dir(s))
可迭代对象,iterable 与迭代器有什么关系?可迭代对象可以转换成迭代器(可迭代对象.__iter__())。
s1 = s.__iter__()
print(s1) #iterator 遵循迭代器协议
迭代器的取值:(迭代器.__next__())
#迭代器取值:
s2 = 'abcd'
s3 = s2.__iter__()
print(s3.__next__()) #a
print(s3.__next__()) #b
只含有__iter__方法的数据是可迭代对象,含有__iter__方法,并且含有__next__方法的数据是迭代器
#迭代器的判断:有__iter__方法,并且含有__next__方法的数据是迭代器
l = [1,2,3,4]
print('__iter__' in dir(l)) #True
print('__next__' in dir(l)) #False
liter = l.__iter__()
print('__next__' in dir(liter)) #True
print(liter.__next__()) #1
print(liter.__next__()) #2
print(liter.__next__()) #3
print(liter.__next__()) #4
方法二:测量他是可迭代的还是迭代器:
# 方法二 测试他是迭代器还是可迭代对象
l = [1,2,3]
l_iter = l.__iter__()
from collections import Iterable
from collections import Iterator
print(isinstance(l,Iterable)) #True
print(isinstance(l,Iterator)) #False
print(isinstance(l_iter,Iterator)) #True
print(isinstance(l,list)) #True
迭代器的意义:
1)、迭代器节省内存.
2)、迭代器惰性机制.
3)、迭代器不能反复,一直向下执行.
for 循环的内部机制:
1)、内部含有__iter__方法,他会将可迭代对象先转化成迭代器.
2)、然后在调用__next__方法.
3)、for循环有异常处理的方法.
#用迭代器来表示for循环的内部机制
for i in [1,2,3]:
print(i)
l = [1,2,3]
l_iter = l.__iter__()
while True:
try:
print(l_iter.__next__())
except StopIteration:
break
二、生成器
什么是生成器?
生成器是一次生成一个值的特殊类型函数。可以将其视为可恢复函数。调用该函数将返回一个可用于生成连续 x 值的生成器【Generator】
简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候
又从上次中断的地方开始执行,而生成器内的所有变量参 数都会被保存下来供下一次使用。
生成器的本质就是迭代器,生成器是自己用python代码写的迭代器。
1)、可以用生成器函数;
2)、可以用各种推导式构建迭代器;
3)、可以通过数据转化。
生成器函数:
#生成器函数 生成器
def gener():
print('aaa')
yield 222
print('bbb')
yield 333
print('ccc')
g = gener()
print(g) #<generator object gener at 0x004A2D80>
print(g.__next__()) #aaa
#222
print(g.__next__()) #bbb
#333
return yield 区别:
return 返回给调用者值,并结束此函数.
yiled 返回给调用者值,并将指针停留着当前位置.
def func():
for i in range(10):
yield i
g_func = func()
for i in range(3):
print(g_func.__next__()) #0 1 2
for i in range(3):
print(g_func.__next__()) #3 4 5
send和next:
1)、send 具有和next一样的功能;
2)、send给上一个yiled 整体发送一个值;
3)、send不能给最后一个yield发送值;
4)、获取第一个值的时候,不能用send 只能用next。
def gener():
yield 222#AAA
count = yield 333
print('-------->',count)
yield 'aaa'#NONE
yield 'bbb'
g = gener()
print(g.__next__())#222
print(g.send('AAA'))
print(g.send(None))
print(g.send('AAAA'))
打印结果:
222
333
--------> None
aaa
bbb