关于 python-best-practices
面向 Python 开发者的编写、审查与重构指南,适用于 Python 3.11 及以上版本。75 条规则按影响程度排序,并提供不适用情形,帮助判断哪些建议应结合上下文采用。
主要功能
- 01涵盖八类的 75 条规则
- 02按影响程度排列规则
- 03面向 Python 3.11 及以上版本
- 04提供规则不适用情形
适用场景
- 01审查 Python 代码的正确性
- 02为新建 Python 模块采用实践建议
- 03重构正在修改的代码
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ nathan-gage/ python-skills --skill python-best-practices安装后在 Claude Code 中输入/python-best-practices确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
AGENTS.mdmetadata.jsonREADME.mdrules/_sections.md_template.mdapi-deprecated-aliases.mdapi-immutable-transforms.mdapi-instance-vs-module-fn.mdapi-keyword-only-params.mdapi-model-cohesion.mdapi-no-boolean-flag-params.mdapi-no-private-access.mdapi-required-before-optional.mdapi-underscore-for-private.mddata-aware-datetimes.mddata-delete-dead-variants.mddata-derive-dont-store.mddata-discriminated-unions.mddata-encapsulate-mutable-state.mddata-explicit-variants.mddata-mutable-defaults.mddata-mutation-contract.mddata-newtype-for-ids.mddata-phased-composition.mddata-reject-bool-as-int.mddata-sentinel-when-none-is-valid.mderror-assert-debug-only.mderror-assert-never-exhaustiveness.mderror-consolidate-try-except.mderror-context-managers.md详细介绍
Python 最佳实践
编写和审查 Python 代码的指南。涵盖 8 个类别的 75 条规则,并按影响程度排序。
匹配某条规则只是一个信号,并非判定。大多数规则是针对新代码的设计偏好,并非需要在整个代码库中修复的缺陷——在审查中指出或重构稳定代码之前,请先查看规则的影响级别。
快速参考条目是触发条件,不是授权:在将规则作为审查意见或转换依据之前,请打开规则文件并检查其反向信号——以标记开头的段落(**When ...** / **Scope:** / **Preserve ...**),其中说明了何时不应应用该规则。
适用场景
- 编写新的 Python 模块、函数、类或数据模型
- 审查代码的正确性或类型安全性
- 重构正在编辑的代码中的模式
避免将这些规则作为一刀切的全面清理应用于稳定代码——这种折腾很少值得。
影响级别
CRITICAL— 防止真实的错误类型(数据损坏、吞掉取消信号、不安全的默认值)。发现时应修复。HIGH— 能显著提升正确性或可维护性。大多数情况下值得修复。MEDIUM— 良好实践;有助于提升清晰度或防止偏离。应用于新代码;不要折腾稳定代码。LOW-MEDIUM/LOW— 风格或微优化。有机会时应用。
Python 版本基准
规则以 Python 3.11+ 为前提。依赖更高版本的规则会在文中注明:
warnings.deprecated()— 3.13+zoneinfo— 3.9+isinstance()中的联合类型 — 3.10+assert_never— 3.11+(可通过typing_extensions回移植)- PEP 695
type语句和泛型语法 — 3.12+(在types-modern-syntax中注明)
标记为 applicability:pydantic 的规则特定于 Pydantic。
按优先级排列的规则类别
| 优先级 | 类别 | 影响 | 前缀 |
|---|---|---|---|
| 1 | 数据建模 | HIGH | data- |
| 2 | 错误处理 | MEDIUM-HIGH | error- |
| 3 | 类型安全 | MEDIUM-HIGH | types- |
| 4 | API 设计 | MEDIUM | api- |
| 5 | 代码简化 | LOW-MEDIUM | simplify- |
| 6 | 性能 | LOW-MEDIUM | perf- |
| 7 | 命名 | LOW-MEDIUM | naming- |
| 8 | 导入与结构 | LOW | imports- |
类别影响级别是典型情况的标签;单条规则的影响可能高或低一个级别——请查看规则文件。
快速参考
数据建模(data-)
data-mutable-defaults— 绝不要写def f(items=[]);使用None并在函数体中构造,或使用default_factorydata-derive-dont-store— 根据状态计算布尔值;不要缓存彼此镜像的标志data-mutation-contract— 每个函数只采用一种明确的约定:修改对象(返回新信息也可以),或返回新对象——绝不要把已修改的对象当作全新对象返回data-aware-datetimes— 使用带时区的datetime.now(timezone.utc);utcnow()已弃用data-discriminated-unions— 为不同变体添加标签,而不是使用装满可选字段的对象data-explicit-variants— 每种模式使用具体类,优于is_thread/is_edit标志data-phased-composition— 将同时出现的可选项归入一个嵌套可选项data-encapsulate-mutable-state— 将可变状态限制在范围最小且明确的作用域内data-sentinel-when-none-is-valid— 当None是有意义的值时,使用私有哨兵值data-newtype-for-ids— 使用NewType('UserId', str),避免 ID 被混用data-delete-dead-variants— 移除不会被构造的联合类型分支data-reject-bool-as-int—bool是int的子类;在数值检查前应显式拒绝它
错误处理(error-)
error-specific-exceptions— 捕获特定类型的异常;绝不要使用裸except:或except BaseException:(会破坏 Ctrl-C 和异步取消);在 3.8 及更高版本中,except Exception:不会影响取消error-context-managers— 对文件、锁和会话使用with/async witherror-assert-debug-only—assert在-O下会被移除;不要将其用于运行时契约error-validate-at-boundaries— 在系统边界处尽早失败,避免进行昂贵的操作error-trust-validated-state— 信任不可变且在本地构造的状态error-consolidate-try-except— 合并捕获和处理方式相同的代码块error-assert-never-exhaustiveness— 使用typing.assert_never检查穷尽性error-raise-from-for-chains— 使用raise NewErr(...) from original保留因果关系error-inherit-base-exceptions— 新异常继承现有基类,以保持兼容性error-log-exception-context— 在except中使用logger.exception(...);在日志中保留回溯信息error-repr-in-messages— 在错误文本中使用f"tool {name!r}"表示标识符error-match-types-not-messages— 根据异常类型和状态码进行分类,绝不要匹配消息子串
类型安全(types-)
types-fix-errors-not-ignore— 修复类型错误;# type: ignore是最后的手段types-avoid-any— 优先使用 Protocol、TypeVar 和联合类型,而不是Anytypes-typeddict-over-dict-any— 结构已知时使用TypedDict/ dataclasstypes-literal-for-fixed-sets— 固定字符串使用Literal["a", "b"]types-fix-types-not-cast— 修复定义;仅在运行时确实进行了窄化时才使用cast()types-isinstance-for-narrowing— 使用isinstance(),而不是hasattr/type(x).__name__types-narrow-to-runtime-reality— 注解应与控制流实际允许的情况相符types-trust-the-checker— 移除类型已能保证的运行时检查types-remove-redundant-optional— 值保证存在时,移除| Nonetypes-type-checking-imports— 对可选或较重的导入使用if TYPE_CHECKING:types-modern-syntax— 使用X | None、list[str];不要使用Optional/Union/typing.Listtypes-sequence-over-list-params— 只读参数使用Sequence/Mapping;list是不变的
API 设计(api-)
api-required-before-optional— 必填字段放在可选字段之前(Python 会强制要求)api-keyword-only-params— 使用*标记可选参数或配置参数api-no-boolean-flag-params— 使用Literal/Enum,而不是混杂的True、Falseapi-immutable-transforms— 返回新的集合;不要修改输入api-model-cohesion— 使用扁平模型;不要添加重复字段或只包含一个键的包装字段api-underscore-for-private— 内部成员使用_prefix;从__all__中排除api-deprecated-aliases— 对重命名的 API 使用warnings.deprecated()(3.13+)api-no-private-access— 不要从模块外部访问_prefixed名称api-instance-vs-module-fn— 选择与所有权相匹配的命名空间
代码简化(simplify-)
simplify-early-return— 尽早返回;不要嵌套正常路径simplify-extract-after-duplication— 第二次重复时考虑提取;第三次则默认提取simplify-cached-property— 在不可变实例上使用@cached_property;它不是线程安全的simplify-comprehensions— 优先使用推导式,而不是for+.append()simplify-any-all-builtins— 优先使用any()/all(),而不是手动设置标志并使用breaksimplify-fallback-or— 当假值不具有语义时,使用x or defaultsimplify-flatten-nested-if— 没有中间代码时,使用if cond1 and cond2:simplify-inline-single-use-vars— 移除只使用一次的中间变量simplify-remove-dead-code— 删除注释掉的代码;git 会保留历史记录
性能(perf-)
perf-set-for-membership— 对重复的in检查使用setperf-dict-index-over-nested-loops— 构建dict以便查找perf-lru-cache-pure-fns— 对纯函数使用functools.lru_cache/functools.cacheperf-generator-over-list— 在内存或延迟很重要时,使用生成器进行流式处理perf-combine-iterations— 将filter+map合并为一次遍历perf-compile-regex-module-level— 在模块作用域编译静态正则表达式;在紧密循环中尤为重要perf-type-adapter-constant— 在模块作用域定义TypeAdapter(适用范围:pydantic)perf-isinstance-tuple-syntax— 元组形式略快;仅用于经过性能分析的热点路径
命名(naming-)
naming-rename-on-behavior-change— 行为改变时重命名;过时的名称会造成误导naming-consistent-terminology— 同一概念在代码、文档和错误信息中使用同一术语naming-specific-over-generic— 使用toolset_id,而非单独的idnaming-drop-redundant-prefixes— 使用ToolConfig.description,而非ToolConfig.tool_descriptionnaming-upper-case-constants— 使用MAX_RETRIES;内部名称使用_前缀naming-no-type-suffixes— 不使用_dict/_list后缀;类型注解会标明类型
导入与结构(imports-)
imports-no-side-effects— 模块导入必须开销低——导入时不进行网络请求、模型读取或环境变量读取imports-top-of-file— 将导入放在文件顶部;循环依赖、可选依赖或延迟导入等例外情况需注明imports-optional-dependencies— 使用try/except ImportError并提供安装提示imports-scope-helpers-to-usage— 在使用辅助函数的位置附近定义它们imports-remove-unused— 删除未使用的导入imports-no-duplicates— 每个名称只导入一次imports-lightweight-init— 导入任何子模块时都会运行父级__init__.py;避免在其中引入重量级或可选依赖
使用方法
阅读各规则文件以了解详情:
rules/data-mutable-defaults.md
rules/error-specific-exceptions.md
每条规则都包含:
- frontmatter 中的影响级别
- 简要说明
- 错误示例
- 正确示例
- 关于边缘情况的可选说明
完整的编译指南(包含所有规则的详细说明):AGENTS.md
评论
支持 Markdown