一 生成器与yield
若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象
def func(): print('第一次') yield 1 print('第二次') yield 2 print('第三次') yield 3 print('第四次') g=func() print(g) #生成器就是迭代器 g.__iter__() g.__next__() # 会触发函数体代码的运行,然后遇到yield停下来,将yield后的值 # 当做本次调用的结果返回 res=g.__next__() print(res) # 应用案列 def my_range(start,stop,step=1): # print('start...') while start < stop: yield start start+=step # print('end....') for n in my_range(1,7,2): print(n)
总结yield:有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值
二 yield表达式应用
在函数内可以采用表达式形式的yield
def dog(name): print('%s准备吃东西啦'%name) while True: # x拿到的是yield接收到的值 x = yield print('%s吃了 %s' %(name,x))
可以拿到函数的生成器对象持续为函数体send值,如下
g=dog('alex') g.send(None) # 等同于next(g) g.send('肉包子') g.send('一同泔水') g.close() g.send('1111') # 关闭之后无法传值
针对表达式形式的yield,生成器对象必须事先被初始化一次,让函数挂起在food=yield的位置,等待调用g.send()方法为函数体传值,g.send(None)等同于next(g)。
表达式形式的yield也可以用于返回多次值,即变量名=yield 值
的形式,如下
def dog(name): food_list=[] print('道哥%s准备吃东西啦...' %name) while True: # x拿到的是yield接收到的值 x = yield food_list # x = '肉包子' print('道哥%s吃了 %s' %(name,x)) food_list.append(x) # ['一根骨头','肉包子'] g=dog('alex') res=g.send(None) # next(g) print(res) res=g.send('一根骨头') print(res) res=g.send('肉包子') print(res)
三 三元表达式、列表生成式、生成器表达式
3.1三元表达式
三元表达式是python为我们提供的一种简化代码的解决方案,语法如下
res = 条件成立时返回的值 if 条件 else 条件不成立时返回的值
针对下述场景
def func(x,y): if x > y: return x else: return y res=func(1,2)
用三元表达式可以一行解决
x=1 y=2 res = x if x > y else y # 三元表达式
3.2列表生成式
列表生成式是python为我们提供的一种简化代码的解决方案,用来快速生成列表
针对如下场景:
l = ['alex_dsb', 'lxx_dsb', 'wxx_dsb', "xxq_dsb", 'egon'] new_l=[] for name in l: if name.endswith('dsb'): new_l.append(name)
用列表生成式可以一行解决
new_l=[name for name in l if name.endswith('dsb')]
3.3生成器扩展
字典生成式
keys=['name','age','gender'] dic={key:None for key in keys} print(dic) items=[('name','egon'),('age',18),('gender','male')] res={k:v for k,v in items if k != 'gender'} print(res)
集合生成式
keys=['name','age','gender'] set1={key for key in keys} print(set1,type(set1))
3.4生成器表达式
创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成()
(expression for item in iterable if condition)
对比列表生成式返回的是一个列表,生成器表达式返回的是一个生成器对象
g=(i for i in range(10) if i > 3) # !!!!!!!!!!!强调!!!!!!!!!!!!!!! # 此刻g内部一个值也没有 print(g,type(g)) print(g) print(next(g))#调用一次next才会有一个值 print(next(g))
如果我们要读取一个大文件的字节数,应该基于生成器表达式的方式完成
with open('笔记.txt', mode='rt', encoding='utf-8') as f: res = sum(len(line) for line in f) print(res)