本文介绍如何用纯 python(不依赖正则表达式)从文件名列表中提取扩展名并统计出现频次,返回形如 {"txt": 3, "py": 2} 的字典,涵盖基础循环实现与更简洁的现代 python 方案。
本文介绍如何用纯 python(不依赖正则表达式)从文件名列表中提取扩展名并统计出现频次,返回形如 {"txt": 3, "py": 2} 的字典,涵盖基础循环实现与更简洁的现代 python 方案。
要实现“将文件名列表转换为扩展名频次字典”的功能,核心在于两步:提取扩展名(即点号后的部分,不含点)和统计频次。下面分别介绍两种推荐方式——一种是符合题目要求的纯循环实现(修正原始错误),另一种是更健壮、可读性更高的现代 Python 写法。
✅ 修正后的基础循环实现
原始代码存在多处问题:
- split(".") 会将 "image1.jpg" 拆成 ["image1", "jpg"],但未取最后一段;
- arr 是二维列表(如 [["image1","jpg"], ["image2","jpg"], ["preso","pptx"]]),后续却直接用 i in freq 判断,而 i 是列表而非字符串;
- freq[item] = 1 中变量名 item 未定义,应为 i;
- print() 放在 return 之后,永不执行;
- 未处理无扩展名或以点结尾的边界情况(如 "file." 或 ".gitignore")。
以下是修复并增强后的循环版本:
def count_file_types(file_list):
extensions = []
for filename in file_list:
parts = filename.split(".")
# 只有至少含一个点且点不在开头/结尾时才视为有效扩展名
if len(parts) > 1 and parts[-1] != "" and not filename.startswith("."):
extensions.append(parts[-1])
else:
extensions.append("") # 或跳过,此处保留空字符串便于调试
freq = {}
for ext in extensions:
if ext: # 忽略空扩展名
freq[ext] = freq.get(ext, 0) + 1
return freq
# 测试
print(count_file_types(["image1.jpg", "image2.jpg", "preso.pptx"])) # {"jpg": 2, "pptx": 1}
print(count_file_types(["file.", ".gitignore", "doc.pdf"])) # {"pdf": 1}⚠️ 注意:该方法对 ".gitignore"(隐藏文件,扩展名为空)或 "archive.tar.gz"(多级扩展名)仅取最后部分("gz"),若需支持 tar.gz 等复合扩展名,应使用 pathlib 或专用库(如 mimetypes)。
✅ 推荐方案:使用 pathlib + Counter
Python 3.4+ 的 pathlib 提供了跨平台、语义清晰的路径操作;collections.Counter 专为计数设计,代码更简短、鲁棒性强:
from pathlib import Path
from collections import Counter
def count_file_types(file_list):
# .suffix 返回 '.jpg',lstrip('.') 去掉前导点 → 'jpg'
# 自动处理各种边界情况(如无扩展名返回 '',隐藏文件正确识别)
extensions = [Path(f).suffix.lstrip('.') for f in file_list]
# 过滤空字符串(无扩展名的文件)
valid_extensions = [ext for ext in extensions if ext]
return dict(Counter(valid_extensions))
# 示例
print(count_file_types(["image1.jpg", "image2.jpg", "preso.pptx"])) # {'jpg': 2, 'pptx': 1}
print(count_file_types(["README", ".env", "data.json"])) # {'json': 1}? 关键要点总结
- 扩展名提取原则:应取最后一个 . 后的内容,而非简单 split(".")[-1](易受 . 开头/结尾干扰);pathlib.Path(f).suffix 是标准、安全的做法。
- 频次统计优化:优先使用 dict.get(key, 0) + 1 或 Counter,避免重复 if/else 判断。
- 边界情况处理:空扩展名(如 "file")、隐藏文件(如 ".gitconfig")、带点的文件名(如 "my.file.txt")均需考虑。
- 不依赖正则:本方案全程未使用 re 模块,完全满足题目约束。
掌握这两种实现方式,既能应对基础编程练习,也能写出生产环境中可靠、可维护的文件类型分析逻辑。

















