📜  门| GATE-CS-2003 |第 64 题(1)

📅  最后修改于: 2023-12-03 15:12:40.075000             🧑  作者: Mango

题目介绍

题目来源:GATE-CS-2003 题目编号:64

题目描述

以下是一个递归地在某个目录及其所有子目录下查找所有文件名包含 pattern 的文件的 Python 函数:

import os

def find_files(pattern, path):
   for root, dirs, files in os.walk(path):
       for name in files:
           if pattern in name:
               print(os.path.join(root, name))

(a) 在该 Python 程序中,path 参数的作用是什么?它被哪个 os.walk 调用所用到?

(b) 假定将 print 语句替换为 yield 语句(即将此函数转换为一个生成器),如下所示:

import os

def find_files(pattern, path):
   for root, dirs, files in os.walk(path):
       for name in files:
           if pattern in name:
               yield os.path.join(root, name)

该程序的行为及返回值有什么变化?如果该函数很长时间没有调用,其中保存的状态可能会怎样?

题目分析

题目中给出了一个 Python 函数,完成一个通用的任务,即查找目录及其子目录下的所有文件中包含指定的字符串 pattern 的文件,并将文件的路径输出或者返回。

这个函数首先使用 Python 的 os.walk 模块,遍历输入的根目录及其中的所有子目录。针对每个目录,os.walk 返回一个三元组:(dirpath, dirnames, filenames)。分别表示当前目录的路径、当前目录下的所有子目录的名称以及当前目录下的所有文件名称。

该函数遍历 files,即当前目录下所有文件的列表。如果某个文件名包含指定的字符串 pattern,就将该文件的绝对路径 append 进一个列表,并最终将该列表 return 出去。

该函数的缺点是,所有满足条件的文件都被存储在 Python 的一个列表中,对于大量文件达到百万级、亿级别的情况,这样的存储方式会消耗大量内存资源。

另外,该函数的用途有限,它只能输出文件路径,无法对文件进行操作。如果需要对满足条件的文件进行复制、更新等操作,还需要写额外的过程进行操作。

题解

(a) path 参数的作用是指定查找的根目录。它被 os.walk(path) 所使用。

(b) 由于将函数 yield 转换为了一个生成器,因此在函数完成运行后,它并不返回一个列表,而是返回一个生成器对象。生成器对象是一个序列,可以逐一读取列表元素,每次仅返回一个元素,这样极大地减小了存储空间。

在调用这个生成器的返回值之前,生成器并不真正运行,因此并不会占用很多内存资源。但是在返回值之后,生成器将开始运行,并在计算遍历 path 下的所有满足条件的文件。

当这个函数很长一段时间没有被调用时,其状态基本上会被丢失,包括临时变量等。随着时间的推移,这个函数可能会消耗更多的内存资源,并最终可能导致系统错误,因此在调用该函数时,要及时处理所有的生成器对象并释放内存。