什么是Python中的”多行注释”?

在Python中,与许多其他编程语言不同,并没有一个专门的语法符号(例如C/C++或Java中的/* ... */)来定义一块真正的“多行注释”。

取而代之的是,Python社区通常使用两种主要的方法来达到类似的目的:

  1. 使用多个单行注释: 在每一行的开头都加上单行注释符号 #
  2. 使用字符串字面量: 利用多行字符串字面量(由三个单引号 '''...''' 或三个双引号 """...""" 包围)来“模拟”多行注释。当这些字符串字面量没有被赋值给变量或用作表达式的一部分时,Python解释器会简单地解析它们,然后忽略它们。

第二种方法,即使用多行字符串字面量,尤其是当它们出现在特定位置时(如函数、类或模块的第一个语句),会被解释器特殊处理,成为文档字符串(Docstrings)。这是Python中推荐的用来记录代码块用途的标准方式,虽然从技术上讲它们是字符串,但在这些位置它们的功能更接近于其他语言的文档注释。

为什么要使用”多行注释”?

即使Python没有原生支持的“多行注释”语法,我们仍然需要能够编写跨越多行的注释或说明。这主要出于以下几个原因:

  • 详细解释复杂的代码块: 有时候,单行注释不足以完整解释一个函数、一段算法或一个类的作用、工作原理、输入输出等细节。需要多行空间来提供更全面的说明。
  • 暂时禁用代码块: 在调试或测试过程中,我们可能需要临时禁用一段代码,但又不想删除它。将整个代码块用“多行注释”的方式包围起来是一种快速有效的方法,因为解释器会忽略这部分内容。
  • 编写文档字符串(Docstrings): 这是最重要和最常见的用途之一。Python使用特定的多行字符串字面量作为文档字符串,用来描述模块、类、函数或方法的用途、参数、返回值、可能的异常等信息。这些Docstrings可以被工具提取,自动生成API文档。
  • 版权信息或文件头部说明: 在文件的开头通常需要写上作者、创建日期、版权信息、许可协议等。这通常需要多行来完成。

如何编写”多行注释”? (具体方法)

正如前面提到的,主要有两种实现方式:

方法一:使用多个单行注释符号(#)

这是最直接,也是最符合“注释”本义的方法。你在每一行的开头都加上一个 #

示例:

# 这是一个使用多个单行注释符号来
# 模拟多行注释的例子。
# 通常用于解释一段代码或临时禁用代码块。
x = 10
y = 20
# print(x + y) # 这一行被注释掉了

优点: 清晰明了,每一行都是一个明确的注释。严格意义上说,这是真正意义上的“注释”。
缺点: 对于大量代码的禁用,需要手动在每一行前添加/删除 #,这可能比较繁琐(尽管许多代码编辑器提供了快捷键)。

方法二:使用多行字符串字面量(”’ 或 “””)

这是在Python中最常用来实现多行文本块,并且在特定位置被用作Docstrings,或者在其他位置被解释器忽略,从而起到“注释”效果的方法。

可以使用三对单引号 ''' 或三对双引号 """ 来包围文本内容。PEP 257 规范推荐使用三对双引号 """ 来编写Docstrings。

示例(用作非Docstring的“注释”):

”’
这是一个使用三对单引号的字符串字面量。
当它没有被赋值或使用时,
解释器会忽略它,效果类似多行注释。
”’

# 或者使用三对双引号
“””
这是一个使用三对双引号的字符串字面量。
通常推荐用这个来写Docstrings。
但在非Docstring位置,它也像注释。
“””

a = 5
b = 3
# print(a * b) # 同样可以结合单行注释

示例(用作Docstring):

def add(x, y):
“””
这个函数用于计算两个数的和。

参数:
x (int or float): 第一个加数。
y (int or float): 第二个加数。

返回值:
int or float: 两个数的和。
“””
return x + y

class MyClass:
“””这个类用于演示文档字符串的位置。”””
def __init__(self):
“””初始化MyClass的一个实例。”””
pass

优点:

  • 可以轻松包围大块文本,方便临时禁用代码块。
  • 是编写Docstrings的标准方式,支持多行、格式化(如遵循reStructuredText或Markdown格式)。
  • 许多编辑器能正确高亮和折叠这种块。

缺点:

  • 从技术上讲,它们是字符串字面量,而不是语言层面的注释语法。在某些特殊情况下(如在交互式环境中作为语句的最后一行),它们可能会被解释并输出。
  • 如果不是作为Docstring使用,它们仍然会在解释阶段被解析(虽然结果被丢弃),而真正的注释(#)在解析前就被忽略了。但这在实际性能上几乎可以忽略不计。

“多行注释”(字符串字面量形式)和Docstrings的区别

理解这一点非常重要,因为这是Python处理多行文本块的一个核心概念:

  • 字符串字面量用作“注释”: 当一个多行字符串字面量(”’或”””)出现在代码中,但它不是模块、类、函数/方法的第一个语句,也没有被赋值给任何变量时,Python解释器会解析它,但因为它没有任何后续操作,这个字符串对象会被立即丢弃。它的存在不会影响程序的执行流程,因此起到了类似注释的作用。
  • Docstrings: 当一个多行字符串字面量(”’或”””)是模块、类定义内部,或者函数/方法定义内部的第一个语句时,Python解释器会特殊处理它。它不仅会解析这个字符串,还会将它存储在该对象(模块、类、函数)的 __doc__ 属性中。这些字符串可以通过代码(例如 print(my_function.__doc__) 或使用 help() 函数)访问,也可以被文档生成工具(如Sphinx)提取,用于创建文档。它们是程序自描述的重要部分。

简单来说:

位置决定了用途和身份:
在特定位置(对象定义内的第一行)的三引号字符串 = Docstring (有特殊用途,被保存)
在其他位置的三引号字符串 = 被忽略的字符串字面量 (起到了类似注释的作用,但不是严格的注释语法)

在哪些地方会用到这些“多行注释”?

根据上面的讨论,我们可以更具体地列出它们的应用场景:

  • 文件顶部: 使用三引号字符串块来写模块级别的Docstring,包含模块的整体描述、作者、版本、版权等信息。

    “””
    My Awesome Module
    This module contains functions for data processing.

    Author: Your Name
    Date: 2023-10-27
    Version: 1.0
    “””
    # Rest of the module code

  • 类定义内部:class ClassName: 语句后面紧跟着三引号字符串块,作为类Docstring,描述类的功能、属性等。

    class DataProcessor:
    “””
    A class to handle various data processing tasks.

    Attributes:
    data (list): The list of data points to process.
    “””
    # … class methods …

  • 函数或方法定义内部:def function_name(...):def method_name(self, ...): 语句后面紧跟着三引号字符串块,作为函数/方法Docstring,描述函数/方法的功能、参数、返回值、异常等。

    def process_data(data):
    “””
    Processes the input data list.

    Args:
    data (list): A list of numerical data.

    Returns:
    float: The average of the data.

    Raises:
    ValueError: If the input list is empty.
    “””
    if not data:
    raise ValueError(“Input data list cannot be empty”)
    return sum(data) / len(data)

  • 临时禁用代码块: 在调试时,将一段需要跳过的代码块用三引号包围起来。

    # print(“This will execute”)

    ”’
    # This whole block is temporarily commented out
    print(“This will NOT execute line 1”)
    print(“This will NOT execute line 2”)
    result = some_complex_calculation()
    ”’

    # print(“This will execute again”)

    注意:这种方法虽然方便,但因为本质是字符串,如果被注释的代码块内部包含与外层相同的三引号,会导致语法错误。例如,如果用 ''' 包围的代码块内部有 ''',就需要换用 """ 来包围。

  • 在代码行间进行较长的说明: embora não tão comum quanto Docstrings ou desativação de código, você pode usar triplas aspas para explicações mais longas que não se encaixam em uma única linha #. No entanto, muitas linhas # são frequentemente preferidas para comentários explicativos comuns.

总结:如何选择使用哪种方法?

  • 需要编写Docstrings: 必须使用三引号字符串字面量(强烈推荐 """)并放置在模块、类或函数/方法的第一个语句位置。

  • 需要临时禁用大段代码: 使用三引号字符串字面量 ('''""") 包围整个代码块。方便快捷。

  • 需要编写常规的、非Docstring的、跨行但不是特别长的解释性注释: 可以选择使用多个单行注释(每行一个 #)。这更符合传统注释的语义,并且不会引入字符串字面量可能带来的微小解析开销。

  • 文件头部的版权、作者等信息: 通常使用三引号字符串块。

理解Python中没有原生的“多行注释”语法,而是通过多行字符串字面量的特性来实现类似功能(尤其是Docstrings),是掌握Python注释的关键。选择哪种方法取决于你的具体目的:是为了生成文档(Docstrings),还是为了临时屏蔽代码,还是为了写一段纯粹的解释性文本。


python注释多行