Python文件重命名移动代码如何优化多层for循环与if判断
多层嵌套循环的高效替代方案
原实现存在三个明显问题:
- 三层嵌套循环时间复杂度达到
O(n*m*k),文件量稍大时性能下降明显 - 每匹配到一对文件名就重复调用
os.listdir(src)遍历整个源目录,无意义IO开销极高 - 逻辑存在bug:遍历目录时只要当前文件不等于匹配到的item1就直接抛错,实际场景下源目录只要存在其他无关文件就会触发异常,根本无法正常运行
核心优化思路是空间换时间,通过提前构建映射字典把双层循环的前缀匹配变成O(1)查找,同时所有IO操作只做一次,从根源上减少冗余计算和IO开销。
优化后实现
首先把重复的前缀提取逻辑抽成公共函数,保证和原有匹配规则完全一致:
import os import shutil def get_match_prefix(filename: str) -> str: # 完全沿用原有匹配规则:先去掉扩展名,再取--分割的第一段作为匹配键 name_without_ext = filename.split('.', 1)[0] return name_without_ext.split('--', 1)[0]
第一步:提前构建目标文件的前缀映射,只需要遍历一次finalName:
target_map = {} for target_name in finalName: prefix = get_match_prefix(target_name) # 提前校验前缀冲突,避免一个原文件对应多个重命名目标导致覆盖 if prefix in target_map: raise ValueError(f"目标文件存在重复前缀:{prefix},无法确定唯一重命名目标") target_map[prefix] = target_name
第二步:只扫描一次源目录,把文件列表存为集合,后续判断文件存在性只需要O(1)复杂度,不需要反复遍历目录:
existing_src_files = set(os.listdir(src))
第三步:单层遍历待处理的原文件列表,直接通过字典查找匹配的目标文件名,执行重命名和移动操作:
for src_name in filesName: current_prefix = get_match_prefix(src_name) # 字典直接查找对应目标文件,不需要双层循环遍历finalName target_name = target_map.get(current_prefix) if not target_name: # 没有对应重命名目标的文件直接跳过,按需添加日志即可 continue if src_name not in existing_src_files: logger.error(error_message) raise ValueError(error_message) # 执行重命名、移动操作 old_full_path = os.path.join(src, src_name) renamed_full_path = os.path.join(src, target_name) final_dst_path = os.path.join(dst, target_name) os.rename(old_full_path, renamed_full_path) shutil.move(renamed_full_path, final_dst_path)
性能对比
- 原实现时间复杂度为
O(len(filesName) * len(finalName) * len(源目录文件数)),每匹配到一对文件就要重新扫描一次整个源目录,文件量超过100个时IO开销会非常明显 - 优化后时间复杂度为
O(len(filesName) + len(finalName) + len(源目录文件数)),所有遍历均为单层,目录仅扫描一次,前缀查找为O(1)复杂度,哪怕文件量上千性能也不会有明显损耗
额外说明
- 优化逻辑完全保留了你原有的前缀匹配规则,不会出现匹配结果和原逻辑不一致的问题
- 修复了原实现中误抛异常的bug,不会因为源目录存在其他无关文件就中断流程
- 如果需要校验源目录下存在未列入
filesName的文件,可以单独遍历existing_src_files做校验,不会影响核心重命名流程的性能
内容的提问来源于stack exchange,提问作者pipocaDourada
相关产品推荐
相关产品推荐

