五、Python之迭代器与生成器
1. 迭代器
迭代:指的是一个重复的过程,每一次重复称为一次迭代,并且每一次重复的结果是下一次重复的初始值
对于序列类型:str,list,tuple可以依赖索引迭代取值;但对于dict,set,文件等,python必须提供一种不依赖索引的迭代取值的方法
可迭代对象 obj.iter () # str,list,tuple,dict,set,文件
迭代器对象 obj.iter (),obj.next () # 文件
d = {'name':'ee','age':18,'sex':'male'}
d_iter = d.__iter__() #等同于 d_iter = iter(d)
print(d_iter.__next__()) #name #等同于 print(next(d_iter))
print(d_iter.__next__()) #age
print(d_iter.__next__()) #sex
print(d_iter.__next__()) #StopIteration 报异常说明已经迭代完了
#result
name
age
sex
Traceback (most recent call last):
File "E:/Python/OldBoy/20issue/d4/bolog.py", line 6, in <module>
StopIteration
总结:
可迭代对象不一定是迭代器对象
迭代器对象一定是可迭代的对象
可调用 obj.__iter__()方法,得到的是迭代器对象,而对于迭代器对象调用obj.__iter__()得到的仍然是它本身
2. 生成器
生成器:只要在函数内部出现yield关键字,那么再执行函数时就不会执行函数代码,会得到一个结果,该结果就是生成器
生成器本身就是迭代器
def func():
print('====>1')
yield 1
print('====>2')
yield 2
print('====>3')
yield 3
g= func() #g.__iter__() g.__next__():g现在就是一个迭代器
print(next(g))
#result
====>1
1
3.协程函数之yield表达式
yield 功能:
1.提供了一种自定义迭代器对象的方法
2.yield与return相似,但yield可以返回多次值,函数的暂停和执行由yield来控制;而return只返回一次值,且返回之后就结束了
def eater(name):
print('%s ready to eat' %name)
food_list = []
while True:
food = yield food_list
food_list.append(food)
print('%s ready to eat %s' %(name,food))
e = eater('xiaoming')
print(e) #<generator object eater at 0x00000295EF99CF10>
e.send(None) #xiaoming ready to eat #必须先next,若直接send则会报错和 e.send(None)结果一致,相当于先初始化
print(e.send('rice')) #xiaoming ready to eat rice ['rice']
print(e.send('milk')) #xiaoming ready to eat milk ['rice', 'milk']
4.练习
1)用生成器实现range功能
def func(start,stop,step):
while start < stop:
yield start
start+=step
res = func(1,10,2)
while True:
try:
print(next(res))
except StopIteration:
break
2)模拟管道,实现功能:tail -f access.log | grep '404'
import time
#tail 功能
def my_tail(file):
with open(file,'rb') as f:
f.seek(0,2) #直接调到文件末尾
while True:
line = f.readline()
if line:
yield line
else:
time.sleep(0.05)
#grep 功能
def my_grep(lines,pattern):
for line in lines:
line = line.decode('utf-8')
if pattern in line:
yield line
lines = my_tail('./access.log')
print(lines) #<generator object my_tail at 0x000001F6DAF8CF68>
res = my_grep(lines,'404')
print(res) #<generator object my_grep at 0x000001F6DAF8CFC0>
#print
for line in my_grep(my_tail('./access.log'),'404'): #res = my_grep(my_tail('./access.log'),'404')
print(line.strip())