我正在向官方咨询。
我找不到注释(它们以#开头)和docstring(它们应该以'''开头)的语法。快速查看Python grammar specification as of Python 3.6页对这两种情况都没有帮助-docstring在那里被定义为longstrings但在语法规范中没有出现名为STRING的类型将进一步显示,但不会引用其定义。
鉴于此,我很好奇cpython编译器如何知道注释和docstring是什么。这项壮举是如何完成的?
我最初猜测,cpython编译器会在第一次传递时删除注释和docstring,但接下来的问题是help()如何能够呈现相关的docstring。

最佳答案

第一节
评论怎么办?
在标记化/词法分析过程中,注释(任何前面的“#”都被忽略),因此不需要编写规则来解析它们。它们不向解释器/编译器提供任何语义信息,因为它们只是为了提高程序的详细程度,因此会被忽略。
这是ansi c编程语言的lex规范:http://www.quut.com/c/ANSI-C-grammar-l-1998.html。我想提醒您注意这里处理评论的方式:

"/*"            { comment(); }
"//"[^\n]*      { /* consume //-comment */ }

现在,看看int的规则。
"int"           { count(); return(INT); }

以下是处理int和其他标记的lex函数:
void count(void)
{
    int i;

    for (i = 0; yytext[i] != '\0'; i++)
        if (yytext[i] == '\n')
            column = 0;
        else if (yytext[i] == '\t')
            column += 8 - (column % 8);
        else
            column++;

    ECHO;
}

在这里,它以ECHO语句结束,这意味着它是一个有效的标记,必须被解析。
下面是处理注释的lex函数:
void comment(void)
{
    char c, prev = 0;

    while ((c = input()) != 0)      /* (EOF maps to 0) */
    {
        if (c == '/' && prev == '*')
            return;
        prev = c;
    }
    error("unterminated comment");
}

这里没有。所以,什么都不退还。
这是一个典型的例子,但是python做了完全相同的事情。
第二节
docstrings怎么了?
注:我的回答的这一部分是对@martijnpieters回答的补充。这并不意味着要复制他在岗位上提供的任何信息。现在,说到这里,。。。
我最初猜测注释和docstring在
cpython编译器的第一次传递[…]
DocStrings(未分配给任何变量名的字符串文本,以及ECHO'...'"..."'''...'''内的任何内容)确实得到了处理。它们被解析为简单的字符串文本("""..."""标记),正如martijn pieters在his answer中提到的。对于当前的文档,传递中只提到docstring被分配给函数/类/模块的STRING+属性。它是如何做到的,并没有真正深入地提到任何地方。
实际发生的情况是,它们被标记并被解析为字符串文本,生成的解析树将包含它们从解析树生成字节码,docstring在__doc__属性中的正确位置(它们不是下面所示的字节码的一部分)。我不会详细讨论,因为我在上面链接的答案描述了同样的细节。
当然,完全忽略它们是可能的。如果使用__doc__python -OO标志表示“强烈优化”,而不是-OO表示“温和优化”),生成的字节码存储在-O文件中,不包括docstring。
如下图所示:
使用以下代码创建文件.pyo
def foo():
    """ docstring """
    pass

现在,我们将使用普通标志集编译这段代码。
>>> code = compile(open('test.py').read(), '', 'single')
>>> import dis
>>> dis.dis(code)
  1           0 LOAD_CONST               0 (<code object foo at 0x102b20ed0, file "", line 1>)
              2 LOAD_CONST               1 ('foo')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (foo)
              8 LOAD_CONST               2 (None)
             10 RETURN_VALUE

如您所见,字节码中没有提到docstring但是,他们在那里为了得到docstring,你可以…
>>> code.co_consts[0].co_consts
(' docstring ', None)

因此,如您所见,docstring确实保留下来,只是不作为主字节码的一部分。现在,让我们重新编译此代码,但优化级别设置为2(相当于test.py开关):
>>> code = compile(open('test.py').read(), '', 'single', optimize=2)
>>> dis.dis(code)
  1           0 LOAD_CONST               0 (<code object foo at 0x102a95810, file "", line 1>)
              2 LOAD_CONST               1 ('foo')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (foo)
              8 LOAD_CONST               2 (None)
             10 RETURN_VALUE

不,不同,但是…
>>> code.co_consts[0].co_consts
(None,)

docstrings现在不见了。
-OO-O标记只删除一些内容(默认情况下,字节码优化是完成的……-OO从生成的字节码中删除assert语句和-O套件,而if __debug__:另外忽略docstring)。生成的编译时间将略有减少。此外,执行速度保持不变,除非有大量-OOassert语句,否则对性能没有影响。
另外,请记住,只有当docstring是函数/类/模块定义中的第一项时,才会保留docstring所有额外的字符串在编译期间都会被删除如果将if __debug__:更改为以下值:
def foo():
    """ docstring """

    """test"""
    pass

然后对test.py重复相同的过程,在编译时存储在optimization=0变量中:
>>> code.co_consts[0].co_consts
(' docstring ', None)

也就是说,co_consts被忽略了。您会感兴趣的是,这个删除是作为字节码基础优化的一部分完成的。
第三节
附加读数
(你可能和我一样感兴趣。)
What does Python optimization (-O or PYTHONOPTIMIZE) do?
What do the python file extensions, .pyc .pyd .pyo stand for?
Are Python docstrings and comments stored in memory when a module is loaded?
Working with compile()
""" test """模块
dis(由martijn提供)-所有编译器优化的源代码。如果你能理解的话,这真是太迷人了!

10-07 17:22