python-3.x - 编写递归函数列出parts.txt的所有路径
问题描述
编写一个函数 list_files_recursive,它返回所有 parts.txt 文件的路径列表,而不使用 os 模块的 walk 生成器。相反,该函数应该使用递归。输入将是目录名称。这是我到目前为止的代码,我认为它基本上是正确的,但是发生的事情是输出不是一个完整的列表?
def list_files_recursive(top_dir):
rec_list_files = []
list_dir = os.listdir(top_dir)
for item in list_dir:
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
list_files_recursive(item_path)
else:
if os.path.basename(item_path) == 'parts.txt':
rec_list_files.append(os.path.join(item_path))
print(rec_list_files)
return rec_list_files
这是我得到的输出的一部分(来自 print 语句):
['CarItems/Honda/Accord/1996/parts.txt']
[]
['CarItems/Honda/Odyssey/2000/parts.txt']
['CarItems/Honda/Odyssey/2002/parts.txt']
[]
所以问题是它不是一个列表,而且那里有空列表。我不太清楚为什么这不起作用,并且已经尝试了一切来解决它。对此非常感谢任何帮助!
解决方案
这非常接近,但问题是list_files_recursive
' 子调用不会将结果传递回父级。做到这一点的一种方法是将来自每个子调用的所有列表连接在一起,或者通过调用链一直传递对单个列表的引用。
请注意,在中,只有一个参数rec_list_files.append(os.path.join(item_path))
是没有意义的。应该省略,因为它会使输出难以解释——只在调用者中打印。此外,os.path.join
print(rec_list_files)
else:
if ... :
在这里可以更清楚地写出来,elif:
因为它们在逻辑上是等价的。尽可能减少条件嵌套总是一个好主意。
这是通过扩展父列表起作用的方法:
import os
def list_files_recursive(top_dir):
files = []
for item in os.listdir(top_dir):
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
files.extend(list_files_recursive(item_path))
# ^^^^^^ add child results to parent
elif os.path.basename(item_path) == "parts.txt":
files.append(item_path)
return files
if __name__ == "__main__":
print(list_files_recursive("foo"))
或者通过调用树传递一个结果列表:
import os
def list_files_recursive(top_dir, files=[]):
for item in os.listdir(top_dir):
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
list_files_recursive(item_path, files)
# ^^^^^ pass our result list recursively
elif os.path.basename(item_path) == "parts.txt":
files.append(item_path)
return files
if __name__ == "__main__":
print(list_files_recursive("foo"))
这些函数的一个主要问题是它们只能用于查找精确命名的文件parts.txt
,因为该字符串文字是硬编码的。这使得它除了直接目的之外几乎毫无用处。我们应该添加一个参数,允许调用者指定他们想要搜索的目标文件,使函数具有通用性。
另一个问题是该函数并没有像它的名字所声称的那样做:list_files_recursive
应该真的被调用find_file_recursive
,或者,由于硬编码的字符串,find_parts_txt_recursive
。
除此之外,该函数是转换为生成器函数的有力候选者,这是用于遍历的常见 Python 习惯用法,特别是在子目录可能包含大量数据的情况下,这些数据一次保存在内存中会很昂贵。生成器还允许灵活地使用该函数在第一次匹配后取消搜索,从而进一步增强其(重)可用性。
关键字还使yield
函数代码本身非常干净——我们可以避免完全保留结果数据结构的问题,只需按需触发结果项。
我是这样写的:
import os
def find_file_recursive(top_dir, target):
for item in os.listdir(top_dir):
item_path = os.path.join(top_dir, item)
if os.path.isdir(item_path):
yield from find_file_recursive(item_path, target)
elif os.path.basename(item_path) == target:
yield item_path
if __name__ == "__main__":
print(list(find_file_recursive("foo", "parts.txt")))
推荐阅读
- javascript - 如何从具有相似值的其他 2 个对象数组创建对象数组?
- ios - Swift中括号内数字的正则表达式
- c# - 无法设置路径 ASP.NET_sessionid cookie
- python - 如何比较工作人员时间范围内的事务时间点以将员工添加到熊猫的事务表中?
- javascript - EXACTLY return 语句的工作原理
- c++ - C++ - 散列/映射一个 std::vector
在单个 uint64_t - sql-server - 设置 exec sp_executesql 变量
- spring - Flux 为 StepVerifier 返回未排序的数据
- r - 带有ggplot2的发散堆积条形图:图例中的因子排序问题
- javascript - “npm run build”导致 ETXTBSY: text file is busy 错误