python-idiomslisted
Install: claude install-skill Wade-DevCode/awesome-coding-skills-cn
# Python 惯用法
## 何时用
- 写新的 Python 函数、类或模块时。
- Review Python 代码、发现有 C 风格循环或裸 `except` 时。
- 设计数据结构、选择容器类型时。
- 配置项目依赖或虚拟环境时。
- 给已有 Python 代码加类型注解或重构时。
## 核心规则
### 1. 用语言特性,不写 C 风格循环
**规则:** 优先使用列表/字典/集合推导式、`enumerate`、`zip`、生成器表达式;凡是靠下标手动累加的循环,基本都有更地道的写法。
**为什么:** AI 生成 Python 代码时极容易退化成 Java/C 风格:`for i in range(len(arr)): result.append(arr[i] * 2)`。这种写法既啰嗦又容易因下标越界出 bug,而且完全没有利用 Python 的高阶抽象。读者一眼扫过去就知道这段代码不是"Python 人"写的。
**怎么做:**
- 遍历并需要下标 → `enumerate(seq)`,不要 `range(len(seq))`。
- 同时遍历两个序列 → `zip(a, b)`,不要双重下标。
- 构建新列表/字典 → 推导式;数据量大且只消费一次 → 生成器表达式(括号版)。
- 需要累积结果 → 考虑 `map`/`filter`/`itertools`,但可读性优先于炫技。
---
### 2. 善用标准库与类型注解;函数职责单一,避免可变默认参数陷阱
**规则:** 能用标准库解决的不造轮子;所有公开函数加类型注解;函数只做一件事;默认参数值若是可变对象(`list`/`dict`/`set`)必须用 `None` 代替。
**为什么:** AI 常见错误之一是把可变对象直接当默认参数:`def add_item(item, bucket=[]):`——这个 `bucket` 在所有调用间共享,函数第二次调用时里面已经有上次留下的数据,是 Python 最经典的"幽灵 bug"。类型注解则让 mypy 在运行前就能发现大量错误。
**怎么做:**
- 可变默认参数一律写 `param: list | None = None`,函数体内 `if param is None: param = []`。
- 用 `collections.defaultdict`、`pathlib.Path`、`dataclasses.dataclass` 代替手写字典嵌套、字符串拼路径、裸 `__init__`。
- 类型注解遵循 PEP 604(`X | Y`)和 PEP 585(`list[int]`),Python 3.10+ 不再需要从 `typing` 导入基础类型。
---
### 3. 异常用具体类型,资源用 `with`;不裸 `except`
**规则:** 捕获异常时必须指定类型(`except ValueError`),禁止裸 `except:` 或 `except Exception as e: pass`;打开文件、网络连接、数据库游标等资源必须用 `with` 语句管理。
**为什么:** 裸 `except` 会吞掉 `KeyboardInterrupt`、`SystemExit` 等非异常信号,导致程序无法正常终止;同时把真正的 bug 掩盖掉,让问题在更下游以更难理解的形式爆发。AI 在不确定异常类型时倾向于写 `except Exception`,这是懒惰的防御,不是可靠的错