fix(core): 补齐 get_rng 类型校验,set_seed 覆盖 numpy 旧全局
get_rng 的"共享单例生成器"设计由用户本人提出,本提交只在其上修 bug。 - random_state 判断从 isinstance(x, int) 放宽到 (int, np.integer): np.int64 不是 int 的子类,之前会静默退回全局流、种子被无声忽略 - 非预期类型改成抛 TypeError(含 bool / float / str / list),不再静默降级 - get_rng 签名补上 np.integer 与 Generator,与 docstring 的承诺一致 - set_seed 同时调用 np.random.seed:sklearn / statsmodels 走的是 numpy 旧全局状态,不覆盖它们"提交能重跑"就有洞(带 noqa: NPY002 与理由) - 测试:TestRandom 由 4 条增到 7 条(np.integer、非法类型、共享生成器推进) - 新增 docs/dev/personal-pitfalls.md:个人易错点清单,只追加、不通读, 首批记录本轮 4 个点;docs/README.md 补上 05 与该文件的索引 - STATUS.md:L0 进度说明更新,决策 24 改写(共享单例)、新增决策 25 (src/ 实现默认由用户本人写)
This commit is contained in:
1 parent
658b266614
commit
c93810ffb1
6 files changed
+158
-35
No files matched your search
@@ -67,14 +67,14 @@
|
||||
float 走 `.6g`,`|` 转义,`message` 以引用行附在表后;幂等无副作用
|
||||
- 测试:`tests/test_core.py` 去掉 skip + 新增 3 条
|
||||
(默认值/失败路径/大数组、Markdown 结构、可重复调用)
|
||||
- [x] `core/random.py` 的 `get_rng` / `set_seed`
|
||||
- `get_rng(42)` 固定种子可复现;`get_rng(gen)` 原样返回;`get_rng()` 跟随全局种子
|
||||
- `set_seed(seed)` 除了记住种子,还一并调 `np.random.seed`,
|
||||
让 sklearn / statsmodels 那些走旧全局的库也能复现(全项目**唯一**碰旧接口的地方,
|
||||
带 `# noqa: NPY002` 与理由)
|
||||
- 已知取舍:同一个全局种子下每次 `get_rng()` 拿到**同一条流**(见决策 24)
|
||||
- 测试:`TestRandom` 去掉 skip,并把原来那条"自己测自己"的空转测试换成
|
||||
两条真断言(无参可复现、旧全局被覆盖)
|
||||
- [x] `core/random.py` 的 `get_rng` / `set_seed`(**设计由用户本人写**,Codex 补齐类型校验)
|
||||
- 无参 `get_rng()` 复用**同一个模块级生成器**且会推进:既保证重跑一致,
|
||||
又避免两个都省略 `random_state` 的函数抽到同一串数(原决策 24 的取舍已消掉)
|
||||
- `get_rng` 收 `int` / `np.integer` / `Generator` / `None`,其余类型**抛 `TypeError`**:
|
||||
`np.int64` 不是 `int` 的子类,曾因此静默退回全局流
|
||||
- `set_seed` 同时调 `np.random.seed`,覆盖 sklearn / statsmodels 走的 numpy 旧全局
|
||||
(全项目**唯一**碰旧接口的地方,带 `# noqa: NPY002` 与理由)
|
||||
- 测试:`TestRandom` 共 7 条(可复现、透传、无参跟随、旧全局、np.integer、非法类型、共享推进)
|
||||
- [ ] 剩余 10 项(11 个函数):`load_table` `clean_missing`
|
||||
`detect_outliers` `normalize` `standardize` `describe` `correlation_matrix`
|
||||
`bootstrap_ci` `monte_carlo` `save_figure`
|
||||
@@ -83,15 +83,15 @@
|
||||
|
||||
| 检查 | venv | conda `mcm-toolkit` |
|
||||
|---|---|---|
|
||||
| `pytest` | 28 passed, 45 skipped | 28 passed, 45 skipped |
|
||||
| `pytest` | 31 passed, 45 skipped | 31 passed, 45 skipped |
|
||||
| `import mcm_toolkit` | 0.0.1 / 16 项 | 0.0.1 / 16 项 |
|
||||
| `ruff check` | All checks passed | All checks passed |
|
||||
| `scripts/doctor.ps1` | 跑通 | — |
|
||||
| SALib / pymoo / pyright | 缺失 | 已装 |
|
||||
|
||||
- base 亦已复核:numpy 2.4.6 / scipy 1.18.1 / pandas 3.0.6(与两套环境一致)
|
||||
- skip 的都是等实现的算法行为测试;通过的 28 条 = 20 条公开 API 契约测试
|
||||
(`tests/test_api_surface.py`)+ 8 条 `core` 行为测试(`tests/test_core.py`)
|
||||
- skip 的都是等实现的算法行为测试;通过的 31 条 = 20 条公开 API 契约测试
|
||||
(`tests/test_api_surface.py`)+ 11 条 `core` 行为测试(`tests/test_core.py`)
|
||||
- 三个 `.ps1` 通过 PowerShell AST 语法解析
|
||||
|
||||
### ⚠️ 需要注意 / 遗留
|
||||
@@ -140,7 +140,8 @@
|
||||
| 21 | `Result.__repr__` **不打印 `data` 内容**,只给类型与规模 | 模拟轨迹动辄十万个数,repr 一旦刷屏,traceback / 调试器 / notebook 输出就全废了。要看数据请直接取 `result.data` |
|
||||
| 22 | `Result.summary()` 的行序 = 字典插入顺序,不排序 | 比赛时"想先看哪个指标"自己决定键的插入顺序即可,工具不该替人排序 |
|
||||
| 23 | `set_seed` 内部**允许**调用 `np.random.seed`(带 noqa) | sklearn / statsmodels 默认走 numpy 旧全局状态,只记自己的 `_GLOBAL_SEED` 覆盖不到它们,"提交能重跑"就是假的。旧接口在这一个点上不是"取随机数"而是"设种子",性质不同 |
|
||||
| 24 | `get_rng(None)` 不做 `SeedSequence.spawn` 拆分,同一种子下多条流相同 | 多引入一个模块级计数器,会让"同一次调用顺序不同 → 结果不同",对刚上手的人更难解释。取舍写进 docstring,真要独立流就显式传不同 `random_state` |
|
||||
| 24 | `get_rng(None)` **复用同一个模块级生成器**(会推进),不每次新建 | **用户本人提出**,取代 Codex 原来"每次新建 `default_rng(全局种子)`"的写法——那样两个都省略 `random_state` 的函数会抽到完全相同的数。共享单例既保证重跑一致,又让流自然推进 |
|
||||
| 25 | `src/` 下的实现默认由**用户本人**写,Codex 只改 `tests/` 与 `docs/` | 目标是"一边学一边自己写"。曾出现 Codex 直接落盘 `random.py`、与用户编辑器缓冲区冲突导致保存失败。需要代写时用户会明说 |
|
||||
|
||||
## 下一步
|
||||
|
||||
|
||||
Reference in new issue
Block a user