xuzhengfu / pilot

进入编程世界的第一课
1 stars 0 forks source link

p2-2-docstrings 第二章 程序中的文档 #31

Open xuzhengfu opened 4 years ago

xuzhengfu commented 4 years ago

1. “程序中的文档” 的作用

你在调用函数的时候,你像是函数这个产品的用户。

而你写一个函数,像是做一个产品,这个产品将来可能会被很多用户使用 —— 包括你自己。

产品,就应该有产品说明书,别人用得着,你自己也用得着 —— 很久之后的你,很可能把当初的各种来龙去脉忘得一干二净,所以也同样需要产品说明书。

产品说明书最好能说明这个函数的输入是什么,输出是什么,以及需要外部了解的实现细节(如果有的话,比如基于什么论文的什么算法,可能有什么局限等等)。

程序员往往都很懒,写程序已经很烧脑和费时间了,还要写说明书,麻烦;而且还有个最大的问题是程序和说明书的同步,程序和家电不一样,经常会改,一旦改了就要同步说明书,这真是有点强人所难了。

Python 在这方面很用功,把函数的 “产品说明书” 当作语言内部的功能,也就是你在写代码的时候给每个函数写一点注释,只要这些注释按照某种格式去写,调用函数的人就可以方便的看到这些注释,还能用专门的工具自动生成说明书文档,甚至发布到网上去给你的用户(其他程序员)看。这并不是 Python 发明的方法,但 Python 绝对是主流语言里做的最好的之一,Python 社区提供了好几个这类文档工具,比较流行的有 Sphinx、pdoc、pydoctor 和 Doxygen 几个。

这些工具各有优劣,一般来说对小型项目 pdoc 是最好最快的解决方案,而对比较复杂的项目 Sphinx 是公认的强者。

2. Docstring 简介

Docstrings 就是前面我们提到的 “有一定格式要求的注释”,我们可以在我们书写的函数体最开始书写这些文档注释,然后就可以使用内置的 help() 函数,或者 function 类对象的 __doc__ 这个属性去查到这段注释。

from math import sqrt

def is_prime(n):
    """Return a boolean value based upon whether the argument n is a prime number."""
    if n < 2:
        return False
    if n in (2, 3):
        return True
    for i in range(2, int(sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True

如上所示,docstring 紧接着 def 语句,写在函数体第一行的一个字符串(写在函数体其他地方无效),用三个单引号或者双引号括起来,和函数体其他部分一样缩进,可以是一行也可以写成多行。只要存在这样的字符串,用函数 help() 就可以提取其内容显示出来,这样调用函数的人就可以不用查看你的源代码就读到你写的 “产品手册” 了。

help(is_prime)

结果如下:

Help on function is_prime in module __main__:

is_prime(n)
    Return a boolean value based upon whether the argument n is a prime number.
is_prime.__doc__

结果如下:

'Return a boolean value based upon whether the argument n is a prime number.'

这些示例其实都是小练习,对每一个这样的例子,除了要理解我们正在讲的东西(比如这一章讲函数文档),也要顺便搞清楚这个例子里其他东西,比如怎么判断一个数是不是素数之类的。编程是一门手艺,越练越精。

3. 书写 Docstring 的基本原则

既然学,就要像样 —— 这真的很重要。所以,非常有必要认真阅读 Python PEP 257,也就是 Python 社区关于 docstring 的规范。

简要总结一下 PEP 257 中所强调的部分要点:

  • 无论是单行还是多行的 docstring,一概使用三个双引号括起来;
  • 在 docstring 前后都不要有空行;
  • 多行 docstring,第一行是概要,随后空一行,再写其它部分;
  • 书写良好的 docstring 应概括描述以下内容:参数、返回值、可能触发的错误类型、可能的副作用,以及函数的使用限制等。

类定义也有相应的文档规范建议,你可以阅读 PEP 257 文档作为起步,并参考 Sphinx、numpy/scipy(这是非常著名的 Python 第三方库,我们以后会讲)和 Google 的文档来学习大而规范的项目文档通常是怎么要求的。

Docstring 是写给人看的,所以,在复杂代码的 docstring 中,写清楚 why 要远比写 what 更重要,因为 what 往往可以通过阅读代码来了解,而 why 就要难很多。你先记住这点,以后的体会自然会不断加深。

4. 文档生成工具简介

前面提到过,除了 help__doc__ 这样的内置函数和属性可以方便我们使用 docstring,还有一系列文档工具可以从源代码中的注释自动生成在线文档。

这些工具通常需要在一个项目中做好约定才能顺利使用起来,而且有自己一套对 docstring 的内容与格式要求,比如 Sphinx 标准的 docstring 的书写格式叫做 reStructureText,通过 Sphinx 的工具处理之后可以生成在线文档。

通过插件 Sphinx 也能处理前面提过的 Numpy 和 Google 的格式文档。

小结

  • Python 提供内置的文档工具来书写和阅读程序文档;
  • 对自己写的每个函数和类写一段简明扼要的 docstring 是培养好习惯的开始;
  • 通过扩展阅读初步了解 Python 社区对文档格式的要求。

Logging

2020-03-03 15:11:41 initialize