嵌套函数用Yield:无需直接迭代生成器独立访问生成对象
解决方案:让
get_all_files成为生成器函数 首先看你当前代码的核心问题:get_all_files里用了return result,这会导致函数在第一次循环(处理2000年的文件)就直接返回,后面2001-2003年的文件根本不会被处理。而你需要保留main和get_all_files的模块分离,同时能逐个访问每个生成的对象,最直接的修改就是把get_all_files改成生成器函数,不用动retrieve_file和main的核心逻辑。
修改步骤
- 把
get_all_files里的return result替换成yield result,让它在每次循环时返回一个处理后的结果,直到所有年份处理完成。 retrieve_file不需要改成yield,它的职责就是处理单个文件并返回对应的结果(本地文件名或StringIO对象),当前逻辑完全没问题。
修改后的完整代码
# retrieve_file函数保持原有逻辑不变 def retrieve_file(content, to_download, filename): if to_download: # 将文件下载到本地计算机 with open(filename, 'wb') as f: f.write(content) return filename else: # 不下载,保留为文件对象 output = StringIO() output.write(content) return output # 这里不需要替换为yield # 修改后的get_all_files,转为生成器函数 def get_all_files(to_download): for year in [2000, 2001, 2002, 2003]: content = download_file(year) result = retrieve_file(content, to_download, 'file-%s.pdf' % year) yield result # 用yield代替return,逐个返回处理结果 # main函数无需修改,它本来就是迭代生成器的逻辑 def main(): for file in get_all_files(True): parse_file(file)
为什么这样可行?
当main调用get_all_files(True)时,会得到一个生成器对象,迭代它的时候会逐个执行get_all_files里的循环,每次yield出一个处理后的文件结果(要么是本地文件名,要么是StringIO对象),完全满足你“独立访问每个生成的对象”的需求。同时这种修改完全保留了main和get_all_files的模块分离,不需要调整它们的调用关系,也不会影响retrieve_file的单一职责。
内容的提问来源于stack exchange,提问作者toothpick
相关产品推荐
相关产品推荐

