Python编程如何在递归函数中使用迭代器
作者:frank_haha 发布时间:2023-08-04 11:20:24
首先,想要实现的功能是递归遍历文件夹,遇到满足条件的文件时,用yield返回该文件的位置。
如果不用递归器,可以这样实现:
path_list = []
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
path_list.append(item_path)
return
elif os.path.isdir(item_path):
get_one_cage(item_path, cook_folder_name)
即,深度优先遍历,满足要求时,将item_path补充到列表里,之后返回上一层。
这里有一个问题,需要有一个列表,把所有满足条件的地址全存起来,占内存。
使用迭代器可以用一个,遍历出来一个,省内存
替换为迭代器,最先想到的是,把 return 换成 yield,使用for循环调用迭代器函数
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
yield item_path
elif os.path.isdir(item_path):
get_one_cage(item_path, cook_folder_name)
但是这样的程序跑到内嵌函数时,进不去,我百思不得其解
现在看,应该是因为迭代器函数不是一个函数,不是一个命令语句,它只是一个对象。
简单说就是,python程序一般遵循:动词+名词的结构,或者动词,比如:
a = 1
这句话实际上是把1赋值给了a,是有动词的。
迭代器只是一个名词,必须用for语句调用或者next()方法调用才会执行,或者是print,yield,return等等,反正得加个动词,不能孤零零一个名词。
而且上述代码还有一个漏洞。在第一段代码中,我们用一个全局变量存放遍历结果。在第二段代码里,我们本意是把结果yield到for循环调用的地方,但事实是,程序已经套了好几层了,每次yiled只能返回一层。如下图所示:
综上两点作出如下修改:
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
yield item_path
elif os.path.isdir(item_path):
yield get_one_cage(item_path, cook_folder_name)
程序执行结果如下:
显然是返回了一个迭代器,不是一个str,其逻辑如下图所示:
就好比,本意是:
小明把沙袋传给小红,小红传给小兰
但现在是:
小明把沙袋传给了小红,小红被传了出去
修改如下:
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
yield item_path
elif os.path.isdir(item_path):
yield next(get_one_cage(item_path, cook_folder_name))
逻辑如下:
还有一种情况是学长源码里的:使用for调用迭代器:
def get_one_cage(root: str, cook_folder_name: str):
for item in os.listdir(root).copy():
item_path = os.path.join(root, item)
if item == cook_folder_name:
yield item_path
elif os.path.isdir(item_path):
for i in get_one_cage(item_path, cook_folder_name):
yield i
这使用于多个文件的返回,源码里还配合isfile使用,这里是简化版,所以显得冗余。
两种方式均可以正常使用。
昨天这篇文章写完后,遇到了bug,简单说就是,如果一个文件夹系统没有我们想要的文件,递归到最深一层文件夹时,会报错
1
可以理解为:老板让员工找一样东西,员工外包给编外人员。如果编外人员找到了想要的东西,一路传递回去,可以正常交差。如果没找到,编外人员就会一直找,不停歇,找遍了所有能找到的地方(遍历完整个文件夹)也没能找到,就会报错StopIteration。
因此,问题核心是,没有一个返回机制。修改办法是在遍历最后加一个空返回
def get_one_cage(root: str):
for index, item in enumerate(os.listdir(root)):
item_path = os.path.join(root, item)
if item == 'cooked_xyz':
yield item_path
elif os.path.isdir(item_path):
yield next(get_one_cage(item_path))
elif index == len(os.listdir(root).copy()) - 1:
yield
或者是利用try… except语句处理异常:
def get_one_cage(root: str):
try:
for item in os.listdir(root):
item_path = os.path.join(root, item)
if item == 'cooked_xyz':
yield item_path
elif os.path.isdir(item_path):
yield next(get_one_cage(item_path))
except:
yield
会有如上报错,正常。
最后的yield换成return也是可以的,但最好还是用yield,两个混起来用怪怪的。
个人推荐第二种方法
注:copy()可以不用要
以上就是Python编程如何在递归中使用迭代器的详细内容,更多关于Python编程递归中使用迭代器的资料请关注脚本之家其它相关文章!
来源:https://blog.csdn.net/frank_haha/article/details/120383940


猜你喜欢
- 下一代的 web 已经开始上路了,就在这个星期,MySpace 集成了 Google Gears,雅虎发布了新的 BrowserPlus,G
- 如下所示:function getobj(objs, key, value) {for (var i in objs) {var obj =
- 前言本文主要给大家介绍的是关于在Python3使用PyMongo的方法,分享出来供大家参考学习,下面话不多说了,来一起看看详细介绍:Mong
- Ubuntu Server下启动/停止/重启MySQL数据库的三种方式系统环境:ubuntu server 12.10 x64(mysql为
- 昨时要导一些数据,从网上搜到的。字段多时insert 语句生成的不完整了,还没有找到原因..有个缺点……就是标识种子的列 也insert了c
- 什么是循环呢?简单理解,循环就是反复的去做某一件事情。生活中的例子:比如我们听歌的时候,在歌曲的页面就会出现单曲循环、列表循环、随机播放以及
- dotnet run 介绍dotnet 相关命令是属于 .NET Core command-line (CLI) 的一部分,Microsof
- 今天来说一下,有些刚刚接触python的朋友,在使用pip install安装python 第三方库的过程中会出现网速很慢,或者是安装下载到
- 编这个程序是想过节过年,一些重要的纪念日,给亲戚好友发祝福之类的,但要凌晨0点才显得比较有诚意,可我又比较贪睡,常常忘了,所以就有了编个微信
- 前言人脸识别在LWF(Labeled Faces in the Wild)数据集上人脸识别率现在已经99.7%以上,这个识别率确实非常高了,
- [Q]怎么样查询特殊字符,如通配符%与_ [Q]如何插入单引号到数据库表中 [Q]怎样设置事务一致性 [Q]怎么样利用光标更新数据 [Q]怎
- 测试环境为Windows 10 系统,Python3.7,转换需要提前安装pydub、ffmpeg,安装和加入环境变量配置方法自行解决,至于
- 1 端口映射举个例子来说明一下端口映射的作用。有A、B、C三台计算机,A、B互通,B、C互通,但是A、C不通,这个时候在C上开了一个Web服
- 一、在Yii中实现乐观锁乐观锁(optimistic locking)表现出大胆、务实的态度。使用乐观锁的前提是, 实际应用当中,发生冲突的
- 本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法)。分享给大家供大家参考,具体如下:# coding:utf-8
- 词云图是将词汇按照频率的高低显示不同大小而形成的图,可以一目了然地看出关键词。下面是词云图的python代码~#导入需要模块import j
- 数据库缓存为了使用数据库表作为缓存后端,首先在数据库中运行这个命令以创建缓存表:python manage.py createcacheta
- 1、重装后启动mysql服务,提示 本地计算机无法启动 mysql 服务 错误 1067:进程意外终止。2、查看mysql根目录下有一 计算
- 引言 近期公司vue前端项目需求:实现弹窗的拖拽,四边拉伸及对角线拉伸,以及弹窗边界处理
- 就是一个简单的python查询百度关键词排名的函数,以下是一些简介:1、UA随机2、操作简单方便,直接getRank(关键词,域名)就可以了