【发布时间】:2017-11-27 17:59:09
【问题描述】:
我正在编写一个递归遍历文件系统的函数,并返回带有.txt 扩展名的所有文件的列表。
pass_test_func 参数只是一个可以运行和检查的函数(即文件是否大于 100 字节等) - nothing 函数(设置为默认值)仅返回其参数。
我的实现:
def visit(dname, pass_test_func=nothing):
directory = os.listdir(dname)
byte_list = []
for file in directory:
file_dir = os.path.join(dname, file)
if os.path.isfile(file_dir) and file_dir.lower().endswith('.txt'):
size = os.path.getsize(file_dir)
if pass_test_func(size):
byte_list.append(str(size) + ' ' + file_dir)
elif os.path.isdir(file_dir):
visit(file_dir, pass_test_func)
return byte_list
我的问题是当我在以下几行中递归调用visit
elif os.path.isdir(file_dir):
visit(file_dir, pass_test_func)
byte_list 再次被清空。我明白为什么会发生这种情况,但不知道我将如何解决它。该列表必须在visit 的定义中定义,所以每当我使用递归时,它总是会被重置,不管是什么权利?也许其他一些数据结构更适合,比如元组或字典?
【问题讨论】:
-
您应该知道已经有人努力解决您的问题:docs.python.org/3/library/os.html#os.scandir
-
@KlausD.:或者在较旧的 Python 上,您可以使用 the PyPI
scandirmodule(os.scandir是基于此)。在 Windows 上,这会将系统调用(和相关的 I/O)开销从每个目录三个调用(检查是否文件、检查是否目录、列出目录)+每个文件两个调用(检查是否文件、获取大小)减少到只有一个检查每个目录;在 Linux 上,它无法避免使用stat进行大小检查,但它仍然减少了每个目录一次调用加上每个文件一次调用(DirEntry对象上免费提供了类型检查)。 -
@KlausD.:请注意,在大多数情况下,您最好只使用
os.walk(这是基于os.scandir,一旦os.scandir可用),因为它可以处理很多事情给你的东西。整个函数简化为def visit(dname, pass_test_func=nothing): return [os.path.join(root, f) for root, _, files in os.walk(dname) for f in files if pass_test_func(os.path.getsize(os.path.join(root, f)))]和os.walk(单行,因为这是一个注释;你可以很容易地编写一个适当的生成器函数,它不会一遍又一遍地重复joinroot和f)。
标签: python python-3.x list recursion