fix(stats): CV 改用 |mean|,并记录决策 37/38/39 与经验 12
coefficient_of_variation: - 分母由 mean 改为 |mean|(用户本人改),均值为负时 CV 不再是负值 - docstring 摘要 / Returns / Notes 同步,加一条测试钉住"均值为负时 CV 仍为正" 口径拍板(2026-10-03): - 决策 37: 非数值列的处置按输出契约分,不按包分 —— describe/zscore 丢掉(吐数值结果表), detect_outliers 保留列、掩码恒 False(吐与原表同形的掩码),刻意不统一 - 决策 38: CV 用 sigma/|mean| - 决策 39: 工作约定 —— 语义/非法输入口径由用户拍板,Codex 只列选项不代选; ruff / STATUS.md / CHANGELOG.md / tests / docstring 这类与算法无关的工程事务 Codex 顺手补 经验(docs/dev/personal-pitfalls.md,只追加): - 第 12 条: 三个并列的 if 让后面的静默覆盖前面的(transform.normalize 三种 method 实际只走 max) 第 11 条(上一轮)是 descriptive 的 .loc 对齐失败静默填 NaN —— 两条的共同点是"不抛异常" 验证: pytest 103 passed / 39 skipped;ruff All checks passed;pyright 0 errors。 docs: STATUS.md 决策 37/38/39 + 下一步;CHANGELOG 记录
This commit is contained in:
1 parent
e9624cb3a7
commit
cfc1be31ca
5 files changed
+58
-20
No files matched your search
@@ -177,3 +177,24 @@
|
||||
② 新加的行/列**立刻断言不是全 NaN**,别只看"代码跑过去了";
|
||||
③ 记住这次的信号差异:长度不对(ndarray)会报错,Series **不会** —— 后者更危险。
|
||||
- 首次:2026-10-03|复发:0
|
||||
|
||||
### 12. 三个并列的 `if`,后面的静默覆盖前面的
|
||||
|
||||
- 现象:`normalize` 里三种 method 写成了**三个并列的 `if`**(而不是 `if / elif / else`):
|
||||
`if method == "minmax": result = ...`、`if method == "vector": result = ...`,
|
||||
末尾再来一句无条件的 `result = arr / x_max` 兜住 max。
|
||||
读起来像"三种方法各算各的",实际是**三段顺序执行、逐次覆盖**同一个 `result`:
|
||||
不管传 minmax 还是 vector,算完都被最后那段冲掉 —— 三种方法**实际只走了 max**。
|
||||
docstring 里那行 `>>> normalize([1, 2, 3]).tolist()` → `[0.0, 0.5, 1.0]` 就是活规格,
|
||||
实测出来是 `[0.33, 0.67, 1.0]`,5 条测试一起红。
|
||||
- 为什么会错:脑子里想的是"按 method 分派",手上写成了"按顺序执行"。
|
||||
写第一个 `if` 的时候没意识到"少了 `elif` 就没有互斥",而 `result` 又是同一个变量 ——
|
||||
`if` 只会让**条件为真时**赋值,`elif`/`else` 才负责让**其余分支不执行**。
|
||||
这类错**不报错、不抛异常**,只有断言能抓。
|
||||
- 以后怎么防:① 同一个变量被多个分支赋值时,一律 `if / elif / else`,或让每个分支 `return`,
|
||||
绝不写并列 `if`;② 分派逻辑写完先跑最朴素的那个用例(docstring 的 Examples 就是最好的靶子),
|
||||
别等全量测试;③ 注意 ruff 的 `RET505` 抓的是**反方向**(`return` 后还有 `elif`),
|
||||
并列 `if` 覆盖它完全管不着 —— **lint 不会替你发现这个**。
|
||||
- 同一轮的另一个同类例子见第 11 条(`.loc` 对齐失败静默填 NaN):
|
||||
这两个 bug 的共同点是"**不抛异常**",靠的是断言而不是报错。
|
||||
- 首次:2026-10-03|复发:0
|
||||
Reference in new issue
Block a user