Python3 注释编写完全指南:从基础规范到高效实践

23 阅读10分钟

Python3 注释编写完全指南:从基础规范到高效实践

注释这事儿,说大不大,说小不小。写好了帮你省三个月后的记忆,写砸了比不写还坑人。这篇把注释的规矩、套路和坑一次说清楚。

WEB项目地址:演示地址 安卓APP下载地址:演示地址

① 注释的核心价值与适用场景解析

注释到底是写给谁看的?

写给你的队友看,也写给三个月后的自己看。

代码是写给计算机执行的,但代码也是给人读的。一个函数干了什么事、参数有什么约束、返回值什么格式——这些信息光靠看代码不一定能一眼看出来。注释就是用来补上这段“代码没写明白”的信息。

什么时候该写注释?

  • 复杂的业务逻辑:比如订单金额的计算规则、折扣叠加的顺序
  • 非常规的实现方式:比如“这里故意不用算法 A 而用算法 B,因为 A 在大数据量下会 OOM”
  • 对外暴露的 API / 公共函数:别人要调你的代码,得知道怎么用
  • 临时的处理方案:比如“TODO: 等后端接口上线后替换这里的 mock 数据”

什么时候不用写注释?

代码本身就能说清楚的事,别重复一遍。比如 i += 1 旁边写“i 加 1”——这就是废话。

② 单行注释的正确写法与快捷操作

Python 的单行注释用井号 # 开头。从 # 开始到这一行结束的所有内容,解释器都忽略。

# 计算订单总价,包含税费和运费
total = subtotal * 1.08 + shipping_fee

两条硬规矩:

规矩一:# 后面跟一个空格再写文字。 这是 PEP 8 官方推荐的写法,几乎所有 Python 项目都遵守。

# 好的写法
# 坏的写法(井号后面没空格)

规矩二:注释和代码至少空两个空格。 如果是写在代码行末尾的注释,# 前面至少空两格。

price = 99.9          # 原价,单位美元
discount_rate = 0.2   # 折扣率,目前全场八折

快捷操作:

大多数编辑器里,选中多行按 Ctrl + /(Windows/Linux)或 Cmd + /(Mac)可以批量加/取消单行注释。这个快捷键平时用得最多——调试时临时屏蔽一段代码,一秒钟搞定。

③ 多行注释与文档字符串的区别用法

很多教材说 Python 的多行注释是用三个引号 """''' 括起来——这个说法其实不准确。

三个引号包裹的字符串如果没赋值给任何变量,解释器确实会忽略它,效果上像注释。但它的本质是字符串字面量,不是真正的注释语法。

"""
这是一段被三个引号括起来的文字。
解释器会把它当作一个字符串常量,
但不赋值的话就直接丢弃了。
"""

真正靠谱的多行注释方式:

每行前面都加 #。这是 PEP 8 推荐的做法,也是绝大多数 Python 项目的实际写法。

# 这里实现了一个简单的缓存淘汰策略。
# 当缓存大小超过 max_size 时,
# 移除最早加入的那个条目。
def evict_cache(cache, max_size):
    ...

什么时候用三个引号?

用三个引号写正式的文档字符串(docstring),专门给函数、类、模块写说明文档用的。它不是注释,是文档。下面第④节细说。

④ 函数与类文档字符串的标准结构

文档字符串(docstring)是写在函数或类定义下面的第一行,用三个双引号括起来。它和注释最大的区别是:注释是给人看的,docstring 可以被程序读取。

def calculate_discount(original_price, member_level):
    """根据会员等级计算折扣后的价格。
    
    Args:
        original_price: 原价,单位元,正数。
        member_level: 会员等级,'gold' / 'silver' / 'bronze'。
    
    Returns:
        折扣后的价格,单位元。如果原价无效则返回 -1。
    
    Raises:
        ValueError: 会员等级不在支持范围内时抛出。
    """
    if original_price < 0:
        return -1
    # ... 具体实现

标准结构包含这几块:

  • 第一行:一句话说清楚函数是干嘛的
  • 空一行
  • Args::列出每个参数,说明类型和含义
  • Returns::说明返回值,包括什么情况返回什么
  • Raises:(可选):什么情况会抛什么异常

help() 直接看:

在交互式环境里执行 help(calculate_discount),上面写的 docstring 会直接打印出来。这才是 docstring 的真正价值——不用打开源码就能知道怎么用。

常见的 docstring 风格:

  • Google 风格:上面示例那种,可读性最好,推荐新手用
  • NumPy/SciPy 风格:更详细,参数描述独占一行,适合科学计算项目
  • Sphinx(reST)风格:用 :param name: 这种格式,和 Sphinx 文档生成工具配合用

新手优先用 Google 风格,够用、好读。

⑤ 代码逻辑注释的编写最佳实践

写逻辑注释的核心原则就一条:解释“为什么”,而不是“是什么”。

# 差评:代码已经说明了一切
# 将 total 乘以 0.9
total = total * 0.9

# 好评:说明背后的业务原因
# VIP 用户享受 9 折优惠,这个规则 2023 年 6 月上线
total = total * 0.9

对复杂条件判断加注释:

# 只有已登录、且账户余额大于 100 元、且最近 30 天有消费记录的用户
# 才发放优惠券。这是运营部门 2025 年 Q1 的新规。
if user.is_authenticated and user.balance > 100 and user.last_purchase_days < 30:
    grant_coupon(user)

这种注释的价值在于:三个月后维护这段代码的人(可能是你自己)一看就知道为什么有这些条件,而不是小心翼翼地猜“动了这个会不会炸”。

对“非常规写法”加注释:

# 这里用 while 循环而不是 for,是因为列表在遍历过程中会动态变长,
# for 循环无法正确处理动态变化的长度。
idx = 0
while idx < len(queue):
    process(queue[idx])
    idx += 1

⑥ 避免无效注释与过度注释的技巧

无效注释长什么样?

x = x + 1   # x 增加 1
# 初始化计数器
counter = 0

这种注释纯属凑数。变量名本身就说明了一切。删了它,代码更清爽。

过度注释长什么样?

# 第一步:打开文件
file = open('data.txt')
# 第二步:读取所有行
lines = file.readlines()
# 第三步:遍历每一行
for line in lines:
    # 第四步:去掉末尾换行符
    line = line.strip()
    # 第五步:打印这一行
    print(line)

把“步骤”这种流程性的东西当注释,每行代码配一句解释——纯属噪音。真正有用的不是“做什么”,而是“为什么这么做”。

判断一个注释该不该留,问自己三个问题:

  1. 删掉这个注释,代码还能不能一眼看懂?
  2. 这个注释补充了代码没有表达的信息吗?
  3. 如果我不写这个注释,维护者会误解这段代码吗?

三个问题都回答“是”,才值得写注释。

⑦ 利用注释进行临时调试的方法

注释在调试的时候特别有用——把代码“关掉”比删掉安全。

屏蔽某一段代码:

选中要屏蔽的代码,按 Ctrl + /(Mac 是 Cmd + /),整段变成注释。想恢复再按一次取消注释。

# 发邮件通知用户
# send_notification_email(user, order)
# 记录日志到数据库
# log_to_database(event)

用注释做“开关”:

有时候你想快速切换两种实现,可以这样:

# 正式环境用真实 API
result = call_real_api(params)

# 测试环境用模拟数据(上面那行注释掉,下面这行取消注释)
# result = mock_response(params)

TODO 标记待办:

这不算严格意义的注释,但实际工作中每天都在用:

def process_order(order):
    # TODO: 等支付接口稳定后,加一个重试逻辑
    # FIXME: 这里的税率写死了 0.08,需要改成从配置读取
    # BUG: 订单金额为 0 时这里会除零,下个版本修
    ...

多数编辑器会把 TODOFIXME 高亮显示,一眼就能看到哪些地方还没做完。

⑧ 主流编辑器注释快捷键大全

编辑器 / IDE注释/取消注释(单行)块注释
VS CodeCtrl + /(Win) / Cmd + /(Mac)同上
PyCharmCtrl + /(Win) / Cmd + /(Mac)Ctrl + Shift + /(Win) / Cmd + Shift + /(Mac)
Sublime TextCtrl + /(Win) / Cmd + /(Mac)Ctrl + Shift + /(Win) / Cmd + Shift + /(Mac)
Vimgc 在 Visual 模式下用插件或 :s/^/#/
Jupyter NotebookCtrl + /(Win) / Cmd + /(Mac)同上
IDLE(自带)Alt + 3 注释 / Alt + 4 取消注释无快捷键,手动加 #

记住最通用的那组就行:Ctrl + /(或 Cmd + /)通吃 90% 的编辑器。

⑨ 团队协作中的注释风格统一规范

一个人写代码怎么都行,一群人写代码必须统一规矩。以下是实际团队里最实用的几条:

1. 注释用英文还是中文?

看团队情况。全员英文能力过关就用英文——兼容性最好,GitHub 开源项目也方便。国内团队用中文完全没问题,关键是统一,不要中英混用

2. 用 # 加空格的写法

前面说了,# 后面跟一个空格。所有人统一。

3. docstring 统一风格

定一种 docstring 风格,全团队用同一种。新手团队建议直接定 Google 风格,上手快。

4. 文件头注释

有些团队要求在文件开头写版权、作者、创建日期等信息:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2026 YourCompany. All rights reserved.

实际上现在 Python 3 默认 UTF-8 编码,第二行 # -*- coding: utf-8 -*- 基本不需要了。文件头要不要写、写什么、怎么写,按团队自己的规矩来。

5. 用 linter 自动检查

在项目里配置 flake8pylint,把注释规范加进去。不符合规范的代码提交时会报警告——省得 code review 时候吵。

⑩ 常见注释误区与修正案例演示

误区一:注释和代码不同步

代码改了,注释没改——这是最坑的情况。注释说“返回用户列表”,实际上返回的是字典。看注释的人被带沟里。

修正:修改代码的同时,必须同步更新注释。 做不到就不要写注释,错误注释比没注释更可怕。

误区二:把注释当草稿纸

# 这个函数写得比较烂,后面再优化
# 感觉这里可以加个缓存,但我还不确定
# 这个地方纠结了好久

这种情绪化的自言自语不该出现在正式代码里。要么把思路理清楚再写,要么删掉这些废话。

误区三:注释缩写过多

# init db conn, retry if fail

“db” 还算常见,“init”“conn”“retry” 也还行。但有些团队内部用的生僻缩写,新人完全看不懂。注释是为了让人读懂,不是加密。

误区四:docstring 写得太简略

def parse_config(filepath):
    """解析配置文件。"""

这等于没写。至少要说清楚:配置文件是什么格式、解析失败怎么办、返回什么结构。

一组前后对比:

修改前:

def get_data(id):
    # get data by id
    res = requests.get(url + id)
    # parse json
    data = res.json()
    # return data
    return data['result']

修改后:

def get_user_profile(user_id):
    """从用户中心 API 获取用户基本信息。
    
    Args:
        user_id: 用户的唯一标识 ID,字符串格式。
    
    Returns:
        包含用户昵称、头像 URL、注册时间的字典。
        如果用户不存在,API 返回 404,本函数返回 None。
    
    Raises:
        requests.RequestException: 网络请求失败时抛出。
    """
    api_url = f"{USER_API_BASE}/profile/{user_id}"
    response = requests.get(api_url)
    
    if response.status_code == 404:
        return None
    
    response.raise_for_status()
    payload = response.json()
    return payload.get('result')

修改后的代码:变量名自解释、docstring 完整、逻辑清晰、基本不需要额外的行内注释。这才是注释该有的样子——该写的地方写透,不该写的地方一句废话都没有。