生成器
定义:函数内含有yield关键字的函数运行结果就是生成器,生成器本质上就是迭代器
生成器本身不可以运行,要运行必须通过next()触发运行,for循环中带有next,while循环也要加了next()才能迭代
迭代器就是为了好多没有索引的可迭代对象搞出来的,也只有通过next()才能读出来,结合上边那句话理解
1、重点
生成器,要生成,首先想到return
生成器是迭代器,是可迭代对象,是生成器
迭代器是迭代器,是可迭代对象
可迭代对象指示可迭代对象
2、生成器与return有何区别?
生成器就是一个函数的内存地址,这个函数内包含有yield这个关键字
return只能返回一次函数就彻底结束了,而yield能返回多次返回值
yield和return一样能返回任意值,多个值也是以元组返回
再循环中的yield是第一次的终点,以后每次的起点和终点,
3、yield干了哪些事?
yield把函数变成(生成器,生成器就是)迭代器相当于yield把iter()和next()封装到函数内部
用return返回只能返回一次,而yield返回多次
函数在暂停以及继续下一次运行时的状态由yield保存
yield有两种形式,一种是语句形式(生成器函数)就是和return差不多的,另一个是表达式形式(协程函数其实也是生成器原理)
4、生成器理解示例
def test(): print("first") yield 1#return 1 yield 2 yield 3 g=test()#g是生成器,是可迭代对象是迭代器 print(g) next(g) next(g)#next超出范围还是会报错 print(next(g))#next可以触发迭代器往下走 #运行原理如下: #print(next(g)) #print(next(test()) #运行test()先print("first")然后碰到yield返回1 #然后结束运行 #用for循环输出g for i in g:# print(i) def countdown(n): print("start") while n>0 : yield n n-=1 print("done") g=countdown(5)#g是生成器,是可迭代对象是迭代器 #用next一步一步输出g print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g))#超出范围,打印done后报错StopIteration # 用for循环g for i in g: print(i) #用while循环输出g while True: try: print(next(g)) except StopIteration: break #因为迭代器是一次性的,所以上边三种循环输出方式只能同时用一种
5、利用生成器的特点实现tail -f /tmp/a.txt |grep 'error'的功能
#/usr/bin/env python #定义阶段:定义两个生成器函数 import time def tail(file_path): with open(file_path,encoding="utf8") as f: f.seek(0,2) while True: line=f.readline() if not line: time.sleep(0.5) continue else: yield line def grep(pattern,target): for line in target: if pattern in line: yield line #调用阶段:得到两个生成器对象 g1=tail("/tmp/a.txt") g2=grep("error",g1) #next触发执行改g2生成器函数 ,用for循环或者while循环来 for i in g2: print(i)
6.关于生成器的一道经典面试题
def add(s, x): return s + x def generator(): for i in range(4): yield i base = generator() for n in [1, 11]: base = (add(i, n) for i in base) print(list(base)) ''' 生成器表达式在没有被next的时候它只是一个表达式,只是一个表达式,不是具体的值 当for n in [1, 11]运行完后,n的值就为11了,这个题可以写成以下这种 ''' def add(s, x): return s + x def generator(): for i in range(4): yield i base = generator() n=1 base = (add(i, n) for i in base) n=11 base = (add(i, n) for i in base) print(list(base))