五、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
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())

posted @ 2018-01-02 23:21  丢失固执  阅读(197)  评论(0)    收藏  举报