python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python代码注释

Python入门指南之代码注释的三种写法详解

作者:星河耀银海

本文详细介绍了Python中的三种代码注释方式及其最佳实践,主要内容包括单行注释(#),多行注释('''或""")和文档字符串(docstring),感兴趣的小伙伴可以跟随小编一起学习一下

一、开篇:好代码需要好注释

在上一篇文章中,我们写出了第一行Python代码。今天我们要聊一个看似简单、但很多程序员做了很多年都没做好的话题:代码注释

注释是写在代码里、但不被Python执行的一段文字。它的作用是给读代码的人(包括未来的你自己)解释代码的含义、逻辑和注意事项。

你可能觉得"我写的代码我自己能看懂,不需要注释"。相信我,三个月后回来看你今天写的代码,如果没有注释,你大概率会对着屏幕发呆:“这代码到底是谁写的?”——是你自己写的,但你已经忘了当时的思路。

一个编程高手的标志之一,就是能写出恰到好处的注释。不是越多越好,也不是越少越好,而是"刚好解释清楚为什么这样写"。

二、Python的三种注释方式

Python提供了三种写注释的方式,每种都有自己的用途。

2.1 单行注释:井号

这是最常用的注释方式。以 # 开头,# 之后直到行尾的所有内容都是注释。

# 这是一个单行注释
print('Hello, World!')  # 这行打印一句话,这也是注释

# 下面这行代码计算1到100的和
total = 0
for i in range(1, 101):
    total += i  # 累加每一个数字
print(total)  # 输出结果:5050

单行注释也可以用来临时禁用某一行代码(调试时特别常用):

print('这条会执行')
# print('这条不会执行,因为被注释掉了')
print('这条也会执行')

绝大多数IDE中,选中几行代码然后按 Ctrl + /(Mac:Cmd + /)可以快速注释/取消注释。

2.2 多行注释:三个引号

用三个单引号 ''' 或三个双引号 """ 包裹起来的内容,可以作为多行注释。

'''
这是一个多行注释
可以跨越多行
Python解释器会忽略这些内容
'''

"""
这也是一个多行注释
用双引号也是一样的效果
可以写很多行
"""

技术细节:三个引号在Python中实际上创建了一个字符串对象,只是这个字符串没有被赋值给任何变量,所以Python创建了它之后马上丢弃。因此严格来说这不是"注释",而是一个"被丢弃的字符串字面量"。但在实际使用中,大家都把它当作多行注释来用。

三种引号的使用场景:

# 函数的文档字符串——这是最正式的用法
def calculate_area(length, width):
    """
    计算矩形的面积。

    参数:
        length (float): 矩形的长度
        width (float): 矩形的宽度

    返回:
        float: 矩形的面积
    """
    return length * width

# 代码顶部的模块说明
'''
模块名:用户管理
功能:处理用户的注册、登录、信息修改等操作
作者:张三
日期:2025-05-30
版本:v1.0
'''

# 临时注释掉一大段代码
'''
print('这段代码暂时不需要执行')
print('先用三个引号把它包起来')
print('等需要的时候再解开')
'''

2.3 文档字符串(docstring)

文档字符串是Python中的特殊注释形式,它用 """...""" 包裹,写在函数、类、模块的第一行。它和普通注释最大的区别是:文档字符串可以被程序读取

def greet(name, greeting='你好'):
    """向指定的人打招呼。

    Args:
        name: 被问候的人的名字
        greeting: 问候语,默认为"你好"

    Returns:
        str: 完整的问候语字符串

    Examples:
        >>> greet('小明')
        '你好,小明!'
        >>> greet('小红', '嗨')
        '嗨,小红!'
    """
    return f'{greeting},{name}!'


# 文档字符串可以通过__doc__属性被程序访问
print(greet.__doc__)
# 输出上面写的整个文档

# 也可以用help()函数查看
help(greet)
# 输出格式化的文档

养成写文档字符串的好习惯。对于你自己定义的函数和类,花一分钟写一个简短的文档字符串,几个月后你会感谢现在的自己。

三、什么时候该写注释

3.1 必须写注释的场景

场景一:解释"为什么",而不是"是什么"

没有意义的注释(只是在重复代码):

x = x + 1  # 将x加1

有价值的注释(解释了原因):

x = x + 1  # 补偿索引偏移,因为用户输入的序号从1开始而不是0

场景二:非显而易见的算法或逻辑

# 使用埃拉托斯特尼筛法找出所有质数
def sieve_of_eratosthenes(n):
    is_prime = [True] * (n + 1)
    is_prime[0] = is_prime[1] = False

    # 只需要检查到sqrt(n),因为如果n是合数,
    # 它必定有一个因子小于等于sqrt(n)
    for i in range(2, int(n ** 0.5) + 1):
        if is_prime[i]:
            for j in range(i * i, n + 1, i):
                is_prime[j] = False

    return [i for i in range(2, n + 1) if is_prime[i]]

场景三:带有特殊限制或注意事项的代码

# 注意:这个函数假设输入列表已按升序排列
# 如果列表未排序,返回的结果将是错误的
def binary_search(sorted_list, target):
    # ... 二分查找的实现

场景四:解决特定bug的代码

# 在Windows上,文件路径中的反斜杠需要转义
# 使用os.path.join可以避免平台差异
import os
file_path = os.path.join('data', 'users', 'info.csv')

场景五:TODO和FIXME标记

# TODO: 这里的错误处理需要完善,目前只在理想情况下工作
# FIXME: 当用户名为空时会崩溃,需要添加空值检查
# HACK: 这是一个临时方案,等后端接口好了之后要重构

3.2 不需要写注释的场景

不需要注释一:代码本身已经足够清晰

# 不需要注释
name = '小明'  # 设置名字为小明
age = 20       # 设置年龄为20

# 上面的注释完全是废话,代码已经说得很清楚了

不需要注释二:可以从良好命名中直接看出的逻辑

# 不需要注释——函数名和变量名已经说明了一切
def calculate_average_score(scores):
    total = sum(scores)
    count = len(scores)
    return total / count

不需要注释三:可以抽取为函数的复杂逻辑

# ❌ 一大段需要注释的复杂代码
def process_order(order):
    # 首先验证订单状态,必须是"待发货"
    # 然后检查库存是否充足
    # 如果库存足够,扣减库存
    # 最后更新订单状态为"已发货"
    # ... 20行代码
    pass

# ✅ 拆分为小函数,函数名本身就是最好的注释
def process_order(order):
    validate_order(order)
    check_inventory(order)
    deduct_inventory(order)
    update_order_status(order, '已发货')

四、注释的黄金法则

4.1 注释解释"为什么",代码说明"是什么"

# ❌ 坏注释:重复代码
# 遍历员工列表
for employee in employees:
    # 计算工资
    salary = employee.hours * employee.hourly_rate
    # 打印工资
    print(salary)

# ✅ 好注释:解释背后的意图
for employee in employees:
    salary = employee.hours * employee.hourly_rate
    # 根据公司政策,加班时间按1.5倍计算
    if employee.hours > 40:
        overtime_hours = employee.hours - 40
        salary += overtime_hours * employee.hourly_rate * 0.5
    print(salary)

4.2 注释要保持更新

最危险的注释是过时的注释——代码已经改了,但注释没有同步更新。

# ❌ 危险的过时注释
def calculate_tax(income):
    # 使用2018年的税率(实际上2025年已经改了!)
    if income < 5000:
        return 0
    elif income < 8000:
        return income * 0.03
    # ...

# ✅ 更好的做法:用清楚的代码代替注释
# 税率表直接来自数据,代码本身说明了逻辑
TAX_BRACKETS_2025 = [
    (0, 5000, 0),
    (5000, 8000, 0.03),
    (8000, 17000, 0.10),
    # ...
]

def calculate_tax(income):
    for lower, upper, rate in TAX_BRACKETS_2025:
        if lower <= income < upper:
            return (income - lower) * rate

4.3 注释用英文还是中文

这是中文开发者经常纠结的问题。我的建议:

# 个人学习项目——中文注释完全OK
def binary_search(arr, target):
    """二分查找算法"""
    left, right = 0, len(arr) - 1
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == target:
            return mid   # 找到了
        elif arr[mid] < target:
            left = mid + 1   # 目标在右半部分
        else:
            right = mid - 1  # 目标在左半部分
    return -1  # 没找到

五、实战:给一段代码写注释

让我们通过一个实际例子,看看有注释和没有注释的代码有什么区别。

5.1 没有注释的版本

def f(d, p):
    r = []
    for k, v in d.items():
        if p(v):
            r.append(k)
    return r

data = {'a': 85, 'b': 42, 'c': 96, 'd': 58, 'e': 73}
print(f(data, lambda x: x >= 60))

你能一眼看出这个程序在做什么吗?可能需要花点时间。

5.2 加了注释的版本

"""
学生成绩筛选程序
功能:从学生成绩字典中筛选出及格(>=60分)的学生名单
"""


def filter_by_criteria(data_dict, check_function):
    """
    根据指定的筛选条件,从字典中筛选出符合条件的键。

    参数:
        data_dict (dict): 待筛选的字典,键为学生名,值为成绩
        check_function (callable): 筛选函数,接受一个值,返回True/False

    返回:
        list: 符合条件的键(学生名)列表

    示例:
        >>> scores = {'小明': 85, '小红': 42}
        >>> filter_by_criteria(scores, lambda x: x >= 60)
        ['小明']
    """
    passed_keys = []  # 存储符合条件的学生名
    for key, value in data_dict.items():
        if check_function(value):
            passed_keys.append(key)  # 该学生成绩符合条件,加入结果
    return passed_keys


# 学生成绩数据
student_scores = {
    '小明': 85,
    '小红': 42,
    '小刚': 96,
    '小丽': 58,
    '小华': 73
}

# 筛选条件:成绩大于等于60分(及格线)
def is_passing(score):
    return score >= 60

# 执行筛选并输出结果
passing_students = filter_by_criteria(student_scores, is_passing)
print(f'及格的学生有:{passing_students}')
print(f'及格人数:{len(passing_students)}人')
print(f'不及格人数:{len(student_scores) - len(passing_students)}人')

现在代码的意思非常清楚了。虽然代码行数变多了,但可读性提升了不止一个档次。好的命名加上适当的注释,让这段代码即使给一个完全没见过的开发者看,也能立刻理解它在做什么。

六、各种语言的注释对比

了解其他语言的注释方式,有助于你理解Python注释的特点:

语言单行注释多行注释
Python# 注释'''注释'''"""注释"""
C/C++/Java// 注释/* 注释 */
JavaScript// 注释/* 注释 */
SQL-- 注释/* 注释 */
Bash/Shell# 注释: '注释'
HTMLN/A<!-- 注释 -->

Python不像C/Java那样有专门的多行注释语法,而是巧妙地将字符串字面量复用作多行注释。这个设计体现了Python的极简哲学——少即是多。

七、注释在调试中的妙用

7.1 逐段排查bug

当程序出问题时,注释是最高效的调试工具之一:

def complex_calculation(data):
    # 第一步:数据清洗
    cleaned_data = clean_data(data)
    print(f'清洗后数据条数:{len(cleaned_data)}')

    # 第二步:数据转换(怀疑这里有bug,先注释掉后面,只看前面的输出)
    # transformed_data = transform_data(cleaned_data)
    # print(f'转换后数据条数:{len(transformed_data)}')

    # 第三步:计算
    # result = calculate(transformed_data)
    # return result

    # 暂时返回None,等排查完bug再恢复
    return None

7.2 用注释做"版本控制"

在学习和实验阶段,可以保留多种写法做对比:

# 写法一:使用列表推导式
# squared = [x**2 for x in range(10)]

# 写法二:使用map函数
# squared = list(map(lambda x: x**2, range(10)))

# 写法三:传统for循环——当前采用这种写法,最易读
squared = []
for x in range(10):
    squared.append(x ** 2)

print(squared)

八、本篇小结

注释是写给人的,不是写给机器的。机器根本看不懂你的注释,但三个月后的你自己会感激今天的注释。

核心要点回顾:

  1. 三种注释方式# 单行、'''/""" 多行、docstring文档字符串
  2. 注释解释"为什么",不要只重复"是什么"
  3. 保持注释和代码同步,过时的注释比没有注释更危险
  4. 好的命名是注释的替代品——当代码自己就能说清楚意思时,不需要额外注释
  5. 关键逻辑必须注释:算法原理、业务规则、特殊限制、已知问题

写注释是一种代码素养。它不是额外的负担,而是编码过程中自然的一部分。从今天开始,每写一段代码,养成问自己"别人读到这里能明白吗"的习惯。下一篇我们将进入Python的基础语法——缩进规则和代码块规范。

以上就是Python入门指南之代码注释的三种写法详解的详细内容,更多关于Python代码注释的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文