在编程的世界里,优雅的代码,从来都不是为了取悦计算机,而是为了善待未来的自己、同事,甚至那个素未谋面却要维护你代码的陌生人。
我们写的代码,终将被阅读,所以我认为好的代码自己会说话,而我们要做的就是让它说的更清楚,更有逻辑。
命名艺术:让代码自解释
在主流的编程语言中,变量命名风格主要分为驼峰命名派(CameCase)和蛇形命名派(snake_case),其中驼峰又分为大驼峰(CameCase)和小驼峰(cameCase)。在Python中,大驼峰和蛇形命名两种风格在不同场景中应用的都比较频繁,大驼峰命名主要应用在类名的定义上,其他场景绝大部分都是使用蛇形命名。另一方面 Python 社区普遍遵循的是 PEP 8 规范,强调一致性与可读性。
命名规范速查
| 类型 | 推荐命名方式 | 示例 | 说明 |
|---|---|---|---|
| 模块 | lower_with_under |
utils.py, _private.py |
简短小写,避免下划线开头 |
| 包 | lowercase |
mypackage |
不建议使用下划线 |
| 类 | CapWords(大驼峰) |
DatabaseConnection, User |
异常类应以 Error 结尾 |
| 函数/方法 | lower_with_under() |
get_user_by_id() |
动词开头,描述行为 |
| 常量 | CAPS_WITH_UNDER |
MAX_RETRIES, API_TIMEOUT |
全大写,表示不可变值 |
| 布尔变量 | is_xxx, has_xxx 等 |
is_connected, has_data |
明确表达真假状态 |
| 私有成员 | __private_attr |
__password, __init_db() |
双下划线触发名称重整 |
命名编写原则
- 遵循PEP 8原则(Python官方制定的编码风格指南和建议);
- 命名需要做到名如其意,不要吝啬名字的长度,但除了一些特殊场景,变量名一般不建议超过4个单词;
- 变量的描述性要强,比如:冬天的梅花比花的描述性更强;
- 当命名与关键字冲突时,在变量末尾加下划线,比如:class_;
优秀命名实践
- 增强描述性
1 | # (bad) 描述性弱的名字,过于抽象,看不懂在做什么 |
- 避免歧义
1 | # 容易混淆 |
- 类型暗示
1 | # 集合类型 |
注释之道:解释「为什么」而非「是什么」
好的注释应该解释设计意图,而不是重复代码内容。
Python中的注释主要分为以#开头的单行注释、和以三连字符串("""...""")表示的多行注释或文档注释。
注释编写原则
- 代码块注释,在代码块上一行的相同缩进处以 # 开始书写注释;代码块注释最需要写注释的地方是代码中那些技巧性的部分;对于复杂的操作,应该在其操作开始之前写上若干行注释,对于不是一目了然的代码,应该在其行尾添加注释;
- 代码行注释,在代码行的尾部跟2个空格,然后以 # 开始书写注释,行注释尽量少写;
- TODO注释应该在所有开头处包含“TODO”字符串,紧跟着用括号括起来你的名字,email地址或其他标识符,然后是一个可选的冒号;
- 对于TODO注释的目的是用来表示“将来做某件事”,建议添加指定的日期;
- 英文注释开头要大写,结尾要写标点符号,避免语法错误和逻辑错误,中文注释也是相同要求;
- 改动代码逻辑时,一定要及时更新相关的注释;
注释实践
1. 文档注释(Docstrings):
1 | class DatabaseConnection: |
2. 为什么注释(Why Comments):
1 | # 使用快速排序而不是内置sort,因为需要稳定排序 |
3. 警示注释:
1 | # 注意:这个函数修改传入的列表,而不是返回新列表 |
4. 代码逻辑注释
1 | def merge_sorted_arrays(arr1: list, arr2: list) -> list: |
- TODO注释
1 | # TODO(ssw@gmail.com): Use a "*" here for string repetition. |
- 改良一些不好的注释习惯
1 | # 1. 过度注释 |
导包规范:整洁的代码门面
导入语句应该按照标准库 → 第三方库 → 本地应用的顺序分组排列:
导包编写原则
1 | from __future__ import annotations |
优雅导包实践
1 | # 每行一个导入 |
格式之美:缩进、空行与空格
Python的强制缩进本身就是一个约束美,但我们仍需注意细节,让代码看着更舒服。
缩进与换行
- 使用 4 个空格 缩进(不混用 Tab)
- 单行不超过 120 字符
- 超长语句可用括号隐式续行:
1 | result = ( |
空行规范
- 文件级函数/类之间:两个空行
- 类内方法之间:一个空行
- 函数内部逻辑块之间:一个空行
- 文件末尾:保留一个空行
空格规范
| 场景 | 示例 |
|---|---|
| 操作符两边 | a + b, x == y |
| 逗号后 | [1, 2, 3], func(a, b) |
| 冒号后(字典) | {"name": "Alice"} |
| 注释符号后 | # 这是一个注释 |
| 括号内不加空格 | (1, 2), [x for x in data] |
自动化: 让工具守护代码规范
手动遵循规范太累?那就让工具替我们守规。
常用工具链
Ruff: 极速的Python linter和格式化工具
Black: 无妥协的代码格式化器
isort: 自动规范import语句顺序
mypy: 静态类型检查
3. 自动化工具配置
pyproject.toml 配置示例
1 | [tool.ruff] |
预提交钩子配置
安装后运行
pre-commit install,每次提交自动格式化 + 检查。
1 | # .pre-commit-config.yaml |
写在最后
优秀的代码风格,不是限制,而是解放,它解放了我们的注意力,让我们不再纠结“这变量是啥”,不再困惑“这段代码想干啥”,让我们能够专注于解决真正重要的事:解决问题,创造价值。