yield表达式形式的应用
来源:互联网 发布:南充哪里有淘宝培训 编辑:程序博客网 时间:2024/05/21 17:39
- 基本格式
- 如何给yield传值
- yield表达式形式的应用
- 栗子一吃货函数
- 栗子二模拟linux中的命令 grep -rl 查找内容 目录
基本格式
x = yield 把yield的接收值,赋值给x
def foo(): while True: x = yield # 函数执行到yield处,暂停,yield后面没有任何返回值,默认返回yield None print("x's value is ", x) # next执行,打印出x的值,yield 没有接收任何传值,默认接收None,并赋值给x, # 然后继续执行,返回循环体,又执行到yield处,暂停,返回Noneg = foo()print(next(g))print(next(g))# 运行结果如下:# None# x's value is None# None
如何给yield传值
带有关键字yield
的函数的执行结果就是生成器,假设为g, 调用g.send(value)
方法,就可以给yield
传值。g.send(None)
就是给yield
传None
, 相当于没传,也就等同于next(g)
的执行效果。
注意,g.send(value)
的传值方式是基于一个暂停的位置。也就是说生成器函数必须先执行到yield处,暂停在那里,给yield传值,然后执行next(g)
。因此,在使用g.send(value)
给yield传值前,要进行初始化:next(g)
或者g.send(None)
。
我们可以用装饰器来做生成器的初始化:
def init(g_func): #定义装饰器函数 def wrapper(*args, **kwargs): g = g_func(*args, **kwargs) next(g) # 用next(g)将生成器函数暂停到yield处,以完成初始化 return g return wrapper@initdef foo(): while True: x = yield print("x's value is ",x)g = foo()print(g.send(1)) # 通过装饰器完成了初始化后,就可以直接给yield传值了print(g.send(2))print(g.send(3))# 执行结果如下:# x's value is 1# None# x's value is 2# None# x's value is 3# None
yield表达式形式的应用
栗子一:吃货函数
@init # 用装饰器来初始化函数def eater(name): print('{} is ready to eat!'.format(name)) food_list = [] while True: food = yield food_list # 在暂停处给yield 传值,yield 得到的值赋值给food(给吃货上菜)。再次执行到yield 暂停,返回food_list food_list.append(food) print('{} is eating {}'.format(name, food))e = eater('Seb') # 执行函数,得到一个生成器print(e.send('meat')) # 给yield传值并执行函数print(e.send('fish')) print(e.send('chicken')) # 执行效果如下:# Seb is ready to eat!# Seb is eating meat# ['meat']# Seb is eating fish# ['meat', 'fish']# Seb is eating chicken# ['meat', 'fish', 'chicken']
上面这个栗子,我们也可以通过一个函数来专门生产yield需要的值,然后从外部传给yield,实现程序的协同工作:
@init # 用装饰器来初始化函数def eater(name): print('{} is ready to eat!'.format(name)) food_list = [] while True: food = yield food_list # 在暂停处给yield 传值,yield 得到的值赋值给food(给吃货上菜)。再次执行到yield 暂停,返回food_list food_list.append(food) print('{} is eating {}'.format(name, food))def make_food(target, n): for i in range(n): target.send('food_{}'.format(i)) # target代表一个需要被传值的生成器e = eater('Seb') # 执行函数,得到一个生成器make_food(e, 3)# 执行效果如下:# Seb is ready to eat!# Seb is eating food_0# Seb is eating food_1# Seb is eating food_2
栗子二:模拟linux中的命令 grep -rl ‘查找内容’ /目录
递归的查找某目录下的文件夹及文件,只要是文件内含有”查找内容“的,打印出文件路径。
分析以上需求,有四个步骤:
1. 递归的找出文件路径,结果给下一步
2. 收到路径,打开文件获取文件,把文件对象给下一步
3. 收到文件,打开文件遍历,取出每一行的内容,给下一步
4. 收到一行内容,判断有没有”查找内容“,有的话,把文件名给下一步
5. 收到文件名,打印
下面通过5个函数来实现,函数之间传递值用target.send(value)
;接收值用var = yield
import os# !!!一个惨痛的教训,定义一个函数时,千万不要和系统内置的名字冲突,否则会各种报错!!!def init(func): """ 装饰器传入一个生成器函数,对其进行初始化 :param g_func: :return: """ def wrapper(*args, **kwargs): g = func(*args, **kwargs) next(g) return g return wrapper@initdef search_file(target): while True: dir_path = yield g = os.walk(dir_path) # os.walk(dir_path)得到的结果是生成器,对这个生成器迭代可以拿到一个个元组。 # 每个元组由(当前目录绝对路径,当前目录下的子目录列表,当前目录下的文件列表)三个元素构成。 # 通过拼接当前目录路径和该目录下的文件,就可以得到每个文件的绝对路径。 for par_dir, _, file_path_list in g: # 迭代,解压元组的元素,当前目录的绝对路径赋值给par_dir, # 文件路径的集合赋值给file_path_list。不需要的元素丢给 _ for file_path in file_path_list: file_path = r'%s\%s'% (par_dir, file_path) # 拼接文件的绝对路径 target.send(file_path) # 把结果发送给需要被传值的对象@initdef open_file(target): while True: file_path = yield with open(file_path, encoding='utf-8')as f: target.send((file_path, f))@initdef read_file(target): while True: file_path, f = yield for line in f: res = target.send((file_path, line)) # 返回值res就是下一个函数的执行的返回值,即tag if res: break@initdef grep_file(target, pattern): tag = False while True: file_path, line = yield tag tag = False # 这里保持False状态。否则只要过滤成功一次,tag为True, 那么 if pattern in line: target.send(file_path) tag = True # 匹配出一个文件内包含查找内容后,更改tag的状态,令上一个函数停止遍历该文件,以免发送重复的文件路径。@initdef print_result(): while True: file_name = yield print(file_name)dir_path = r'D:\testdir'g = search_file(open_file(read_file(grep_file(print_result(), 'a'))))g.send(dir_path)# 函数执行结果如下:# D:\testdir\testa\a.txt# D:\testdir\testa\aa.txt# !!!一个惨痛的教训,定义一个函数时,千万不要和系统内置的名字冲突,否则会各种报错!!!
阅读全文
1 0
- yield表达式形式的应用
- yield的表达式形式
- python--生成器:yield的表达式形式,send
- yield表达式, 四种形式
- 栈应用之计算全括号形式的数值表达式
- lambda表达式的形式
- yield的表达式用法 模拟linuxGrep命令
- 15. Python开发--协程函数(yield表达式形式,装饰器)
- 字符串形式的算数表达式
- EL表达式的三元形式
- python生成器的表达式形式
- yield函数的学习及其应用
- Aspect 切点表达式(xml形式,非注解形式的)
- 使用yield表达式
- 浅谈yield from表达式
- 数学运算表达式形式的验证码
- 表达式的前后缀表达形式
- 前、中、后缀形式的表达式
- ubuntu配置nginx+php开发环境
- 联网上传文件操作
- Asp.net五大对象
- Activity生命周期
- vue组件相关
- yield表达式形式的应用
- nexus的私服的搭建(maven私有仓库)
- LeetCode 66 Plus One
- 文件断点续传(一)
- EF查询
- yii框架建立mongo model 以及调用的时候问题
- Java违例控制
- Treap
- Python3中urllib学习笔记