资料 迭代器 生成器 协程
迭代器,python里提供类似装饰器一样的一种语法。
# 依赖下标循环的方法 l = ['a','b','c','d','e'] i = 0 while i < len(): print(l[i]) i+=1 # for循环形式迭代 for i in range(len(l)): print(l[i])
迭代器
只要对象本身有__iter__方法,那它就是可迭代的,只要执行这个方法,它的返回值就是迭代器,这个返回值就有个__next__方法.
dic = {'a':1,'b':2,'c':3} i = __iter__(dic) print(i.__next__()) print(i.__next__()) print(i.__next__()) print(i.__next__()) # 当取的值多于元素本身会抛出StopIteration错误,也可以理解为终止信号 # 为避免爆出异常可以这么做 i = iter(d) while True: try: print(print(next(i)) excet StopIteration: break # python里面的for循环的方式不是按照下标而是将你传入的对象变成迭代器,去__next__ # 在文件中,文件句柄即时迭代器,也是可迭代对象 # 为什么要用迭代器 1.如果像字典,集合,这种无序的又或者文件这种没有索引的,你没有办法像下标那样的取值 2.迭代器的取值方式是统一的,大家都是按照next的方式取值,迭代器的方式取值占内存比列表这种索引取值更节省内存,他next()一下才会生成一个值属于惰性计算。 # 缺点 1.迭代器无法统计有多长,只有到最后一步才能知道多长。指定取值的话,必须一步步的取值下去才能取到。所以使用不灵活 2.迭代器是一次性取值,不能回头。
了解就好了哈
查看可迭代对象
from collections import Iterable,Iterator s = "hello" l = [1,2,3] t = (1,2,3) d = {'a':1} set1 = {1,2,3,4} f = open('a.txt') s.__iter__() l.__iter__() t.__iter__() d.__iter__() set1.__iter__() f.__iter__() f.__iter__() print(isinstance(s,Iterable))
生成器
- 生成器就是一个函数,这个函数内包含有yield这个关键字,生成器是用来生成值的。 生成器也是一种迭代器所以可以 next(g),生成器把函数做成一个迭代器。
- 生成器与return的区别,return只能执行一次而yield可以执行多次,返回多次值
- yield 是把函数变成了迭代器,它使函数可迭代,函数也能够拥有yield使用
from collections import Iterator def test(): print('first') yield 1 yield 2 yield 3 g= test() print(g) #g是一个函数 print(isinstance(g,Iterator)) #判断类型 print(next(g)) print(next(g)) for i in g: print(i) # 生成流程案例 def test(n): print('start') while n>0: yield n n -= 1 print('done') g = test(6) for i in g: print(i) # 生成器场景案例,模仿tail -f /tmp/a.txt | grep 'error' 案例1:作用监控文件改变,类似linux下的tail命令。 import time def tail(file_path): with open(file_path,'r') as f: f.seek(0,2) #移动到最后一行 while True: line = f.readline() 读取当前光标所在位置行。 if not line: time.sleep(0.3) print('>>>') #这里打印表示他在一直监控这个文件,程序不是卡死 continue else: #print(line,end="") yield line g = tail('a.txt') #print(g.next()) for line in g: print(line) import time #定义阶段:定义俩生成器函数 def tail(file_path): with open(file_path,'r') as f: f.seek(0,2) while True: line=f.readline() if not line: time.sleep(0.3) # print('====>') continue else: #print(line,end='') yield line def grep(pattern,lines): for line in lines: if pattern in line: yield line #调用阶段:得到俩生成器对象 g1=tail('/tmp/a.txt') g2=grep('error',g1) #next触发执行g2生成器函数 for i in g2: print(i)
- 协程
- 协程是用到.send方法,它会去给yield传个值,达到管道的作用,他的作用和next方法相似,但是多了一个传值的步骤
def eater(name) print('%s start to eat food' %(name) while True: food = yield print('%s get %s ,to start eat'%(name,food) print('done') name_yield = eater('alex') next(e) name_yield.send('包子') name_yield.send('烧麦') name_yield.send('饺子') def eater(name) print('%s start to eat food' %(name) food_list = [] while True: food = yield food_list print('%s get %s ,to start eat'%(name,food) food_list.append(food) print('done') name_yield = eater('alex') next(e) name_yield.send('包子') name_yield.send('烧麦') name_yield.send('饺子')