python yield 协程_Python递归中使用协程yield

作者:matrix

被围观: 1,587 次

发布时间:2019-06-11

无评论 »

💡NOTICE:这是一个创建于 540 天前的主题,其中的信息可能已经有所发展或是发生改变。

修改递归函数用于遍历目录中文件。

普通操作

def recursive_open_file(path):

rel = []

path_dir = os.listdir(path) # 获取当前路径下的文件名,返回List

for s in path_dir:

new_dir = os.path.join(path, s) # 将文件命加入到当前文件路径后面

if os.path.isfile(new_dir): # 如果是文件

if os.path.splitext(new_dir)[1] == ".txt": # 判断是否是txt

rel.append(new_dir)

else:

rel = rel + recursive_open_file(new_dir)

return rel

# print(type(recursive_open_file(dir))) #

调试yield

想用协程目的是为了想让程序找到相关文件之后中断挂起然后返回数据,避免一次性加载全部资源在内存中。

之前是想的太简单,没用过果真是不知道。

错误版本

def recursive_open_file(path):

path_dir = os.listdir(path) # 获取当前路径下的文件名,返回List

for s in path_dir:

new_dir = os.path.join(path, s) # 将文件命加入到当前文件路径后面

if os.path.isfile(new_dir): # 如果是文件

if os.path.splitext(new_dir)[1] == ".txt": # 判断是否是txt

yield new_dir

else:

yield recursive_open_file(new_dir)

#执行

for i in recursive_open_file(dir):

print(i) #无法获取文件路径

说明:

yield recursive_open_file(new_dir)返回给外部调用层的数据为 ,不是想要的String!!

正常版本

内部再迭代下就好了 🙈

def recursive_open_file(path):

path_dir = os.listdir(path) # 获取当前路径下的文件名,返回List

for s in path_dir:

new_dir = os.path.join(path, s) # 将文件命加入到当前文件路径后面

if os.path.isfile(new_dir): # 如果是文件

if os.path.splitext(new_dir)[1] == ".txt": # 判断是否是txt

yield new_dir

else:

for i in recursive_open_file(new_dir):

yield i

PHP协程递归同理

function openDirectory($path)

{

$dir = dir($path);

while (false != ($entry = $dir->read())) {

if ($entry != "." && $entry != "..") {

$n_path = $path . DIRECTORY_SEPARATOR . $entry;

if (is_dir($n_path)) {

foreach (openDirectory($n_path) as $i){

yield $i;

}

} else {

yield $n_path;

}

}

}

}

//调用执行

$dir = '/Users/panc/Desktop/Python/testfile';

foreach (openDirectory($dir) as $item){

print_r($item);

print_r("\n");

}

协程send操作

按照廖雪峰的协程教程的生产者-消费者模式:

def consumer():

r = ''

while True:

n = yield r

if not n:

return

print('[CONSUMER] Consuming %s...' % n)

r = '200 OK'

def produce(c):

c.send(None)#启动

n = 0

while n < 5:

n = n + 1

print('[PRODUCER] Producing %s...' % n)

r = c.send(n)

print('[PRODUCER] Consumer return: %s' % r)

c.close()#关闭

c = consumer()

produce(c)

笔记:

c = consumer()不会执行consumer函数,因为内部有yield关键字,consumer函数是生成器generator对象。

通过多个断点调适可以看到yield处的代码会中断执行,然后切换到起调函数的位置继续执行

yield r相似于return返回数据,返回给send()方法返回值。

send(n)操作是把n发送给yield r的返回值

c.send(None)用于启动consumer函数,程序会进入while True循环,在yield处中断

这里yield操作相比较递归遍历那头来说更加麻烦些,因为执行的时候会在两个函数之间相互切换,互相发送数据,需要send方法来启动生成器generator对象。consumer内部因为是while true,所以记得要关闭c.close()

参考:

https://www.liaoxuefeng.com/wiki/1016959663602400/1017968846697824

https://github.com/Earthson/RecGen

https://blog.csdn.net/mieleizhi0522/article/details/82142856

https://blog.51cto.com/xtceetg/1874982

PEACE~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值