第2章:命名规范与代码风格——写出让人舒服的代码

说实话,我见过太多能跑但没法维护的代码了。逻辑没问题,性能也还行,可就是读起来像天书。变量名叫 a、b、tmp,函数名全是 do_stuff、process_data。你想想看,三个月后你自己回来看,估计都得挠头。

这一章咱们就聊聊怎么把代码写「干净」。说白了,就是让代码自己会说话。

2.1 命名原则:一个好名字胜过一行注释

我个人的习惯是:命名要能准确表达意图。别怕名字长,怕的是名字误导人。

2.1.1 变量命名

  • 使用有意义的名称:user_count 比 uc 好,is_active 比 flag 好
  • 布尔变量用 is/has/can 开头:is_valid、has_permission、can_edit
  • 避免通用词:data、info、temp 尽量少用
  • 常量全大写加下划线:MAX_RETRY_COUNT = 3

✅ 好例子

# 糟糕的命名
x = get_data()
y = x * 1.2
if y > 100:
    do_something()

# 好的命名
base_price = get_product_price()
discounted_price = base_price * 1.2
if discounted_price > MAX_DISCOUNT_THRESHOLD:
    apply_special_approval()

2.1.2 函数命名

函数名应该是一个动词或动词短语。我在项目中遇到过有人写 user() 这个函数,你猜它是获取用户、创建用户还是删除用户?猜不到。

  • 动作 + 对象:create_user()、delete_order()、send_email()
  • 返回布尔值用 is/has/can:is_available()、has_access()
  • 避免模糊词:handle()、process()、do()

2.1.3 类命名

类名用名词,首字母大写驼峰。我见过有人把类名写成 user_manager,小写下划线——这其实是模块的命名风格,容易混淆。

类型 风格 示例
类 PascalCase UserProfile、OrderService
函数/方法 snake_case get_user_by_id()、send_notification()
变量 snake_case user_name、order_total
常量 UPPER_SNAKE_CASE MAX_CONNECTIONS、DEFAULT_TIMEOUT
私有属性/方法 前导下划线 _internal_cache、_validate_input()

⚠️ 我曾经踩过的坑

我曾经把一个变量命名为 list,结果覆盖了 Python 内置的 list 类型。后面代码里用 list() 构造列表时直接报错。排查了半小时才发现是命名冲突。所以记住:永远不要用 Python 关键字或内置函数名做变量名。

2.2 PEP 8 规范:Python 社区的通用语言

PEP 8 是 Python 的官方风格指南。说白了,就是大家约定俗成的写法。你不遵守也能跑,但团队协作时就会很痛苦。

2.2.1 缩进与空格

  • 4 个空格缩进,不要用 Tab。我见过混用 Tab 和空格的代码,那格式简直没法看
  • 每行不超过 79 个字符,文档字符串/注释不超过 72 个字符
  • 二元运算符前后各加一个空格:a = b + c 而不是 a=b+c
  • 函数参数列表的逗号后加空格:func(a, b, c)

✅ 正确的缩进示例

# 函数参数换行对齐
def create_user(
    name,
    email,
    age=None,
    is_active=True
):
    # 函数体缩进 4 个空格
    user = User(name=name, email=email)
    if age is not None:
        user.age = age
    return user

2.2.2 空行与注释

  • 顶级函数和类之间空两行
  • 类内方法之间空一行
  • 注释用英文或中文都可以,但团队内要统一。我个人习惯用英文注释,因为和代码风格更一致
  • 注释要解释「为什么」,而不是「是什么」。代码本身已经说明了「是什么」
# 不好的注释
x = x + 1  # 给 x 加 1

# 好的注释
x = x + 1  # 补偿循环中的 off-by-one 误差

2.2.3 import 规范

import 语句要按顺序分组,每组之间空一行:

  1. 标准库
  2. 第三方库
  3. 本地应用/库
import os
import sys

import requests
import yaml

from myproject.models import User
from myproject.utils import format_date

2.3 代码格式化工具:让机器帮你干活

手动调整格式?太累了。我建议直接用工具,一劳永逸。

2.3.1 Black:毫不妥协的格式化器

Black 号称「不妥协的代码格式化器」。你用它的规则,它帮你格式化,你没得选。这其实是好事——团队里不用再争论「花括号放哪行」这种问题了。

💡 安装与使用

# 安装
pip install black

# 格式化单个文件
black my_script.py

# 格式化整个目录
black my_project/

# 检查但不修改
black --check my_script.py

Black 的默认配置很合理:每行 88 个字符(比 PEP 8 的 79 宽松一点)、强制使用双引号、自动处理尾随逗号。我在项目中直接把它配到 pre-commit hook 里,提交代码前自动格式化。

2.3.2 autopep8:更温和的选择

如果你觉得 Black 太霸道,可以用 autopep8。它只修复 PEP 8 违规,不会大改你的代码风格。

# 安装
pip install autopep8

# 格式化文件
autopep8 --in-place my_script.py

# 显示差异但不修改
autopep8 --diff my_script.py

我个人更推荐 Black。为什么?因为 autopep8 给了太多选项,团队里还是会有争论。Black 直接一刀切,省心。

2.3.3 集成到编辑器

不管用 VSCode、PyCharm 还是 Vim,都可以配置保存时自动格式化:

编辑器 配置方式
VSCode 设置 "editor.formatOnSave": true,选择 Black 作为格式化器
PyCharm 安装 Black 插件,配置 File Watchers 或外部工具
Vim 使用 black 插件或 :!black %

2.4 本章知识体系

下面这张图帮你理清命名规范与代码风格的核心脉络:

命名规范与代码风格知识体系 命名原则 PEP 8 规范 格式化工具 变量命名 函数命名 类命名 缩进与空格 空行与注释 import 规范 Black autopep8 编辑器集成 核心原则:代码是写给人读的,顺便给机器执行 好代码 = 清晰命名 + 一致风格 + 自动化工具 实践建议 1. 团队统一命名规范,写入项目 README 2. 配置 pre-commit hook,提交前自动格式化 3. 代码审查时把「可读性」作为硬性标准 4. 定期用 flake8 或 pylint 做静态检查

💡 我的个人建议

刚开始写代码时,别太纠结风格。先跑通功能,然后养成习惯:写完代码后用 Black 格式化一遍。慢慢地,你就会形成肌肉记忆,写出来的代码自然就符合规范了。

嗯,这一章的内容就到这里。命名规范和代码风格看起来是小事,但直接影响代码的可维护性。记住一句话:好代码是让人能轻松理解的代码。