第一次个人编程作业

GitHub 仓库链接:https://github.com/lichenyun-77/--77

学号:3224004155

PSP 表格

PSP2.1 阶段 预估耗时(分钟) 实际耗时(分钟)
Planning / 计划 10 10
Estimate / 估计 10 8
Analysis / 需求分析 25 30
Design Spec / 设计文档 20 20
Design Review / 设计复审 10 10
Coding Standard / 代码规范 10 10
Design / 具体设计 30 35
Coding / 编码 100 120
Code Review / 代码复审 20 20
Test / 测试与修复 60 70
Test Report / 测试报告 20 20
Size Measurement / 工作量统计 10 10
Postmortem / 总结改进 15 15
合计 340 378

模块设计与算法

程序按职责拆分为五个函数:parse_arguments 接收三个命令行路径;read_text 负责安全读取 UTF-8 文件;normalize_text 做 Unicode 规范化、大小写统一和空白符清理;calculate_similarity 计算相似度;write_result 以两位小数写入答案文件。main 负责串联流程及统一异常处理。

核心算法使用 difflib.SequenceMatcher 进行字符级序列匹配。它会寻找两篇文本中的连续匹配字符块,并根据匹配程度返回 0 到 1 的浮点数。相比逐字完全相等的比较,该算法可以容忍插入、删除和替换,适合题目中的“增删改”场景。预处理阶段忽略空格、换行和制表符,避免排版不同影响结果;保留标点,使短文本中的实际修改仍能反映到结果中。

流程:

命令行参数 → 读取两篇文件 → 文本规范化 → SequenceMatcher 比较 → 四舍五入写入答案

性能分析与改进

使用 Python 的 cProfile 对计算模块进行性能分析。调用树显示 calculate_similarity 是核心计算函数,其中 difflib.find_longest_match 是主要匹配函数。

文本先进行 Unicode 规范化并去除无意义空白符,能够减少后续比较的数据量,同时消除单纯排版差异带来的干扰。初版性能分析发现 SequenceMatcher 默认会把高频字符视为噪声;在重复中文段落中可能造成得分异常偏低。因此比较时设置 autojunk=False,优先保证中文论文比较结果稳定。

86f023b85fb2915a1ba9e182a387cd51

单元测试

使用 pytest 自动执行了 13 个测试,全部通过。测试覆盖以下路径:完全相同、完全不同、空白符差异、英文大小写、全角字符、插入、删除、替换、两个空文本、单边空文本、缺失文件、命令行成功写出、命令行失败返回。

83e2c92df956653632b690dea83e7fbd

示例:

def test_one_empty_text_has_zero_similarity() -> None:
    assert calculate_similarity("内容", "") == 0.0

代码质量检查使用 flake8 和 pylint。flake8 对 main.py 及测试文件检查通过;pylint 对 main.py 的评分为 10.00/10。Python 编译检查 python -m py_compile main.py 通过。

覆盖率统计使用 pytest-cov 执行,main.py 的语句覆盖率为 86%。

8194b053c70a237b9a5b8c9281358e51

这些用例覆盖了主要正常路径、边界值和异常路径;仍可继续补充超长文本与不同编码文件的集成测试。

异常处理

PaperCheckError 将底层文件异常转化为清晰的中文提示,避免程序直接输出难以理解的调用栈。

异常场景 目标 对应测试
输入文件不存在 防止无效路径导致程序崩溃 test_missing_input_file_raises_clear_error
输入路径是文件夹 拒绝非文件输入 传入目录路径
文件不是 UTF-8 提示用户转换文本编码 构造非 UTF-8 文件
答案文件不可写 保证失败时给出明确原因 传入无权限目录

总结

本次作业让我练习了文件输入输出、命令行参数、文本序列匹配、异常处理和自动化测试。后续可研究按词语、句子或 n-gram 进行比较,并针对更大规模文本加入分块与预筛选策略。

posted @ 2026-09-11 16:49  lichenyun  阅读(18)  评论(0)    收藏  举报