python文档字符串和注释的区别_为什么Python的语法规范不包含文档字符串和注释?...

我正在咨询官方

Python grammar specification as of Python 3.6.

我无法找到任何注释语法(它们显示在#前面)和文档字符串(它们应显示为”’).快速查看the lexical analysis页面也无济于事 – docstrings在那里被定义为longstrings但没有出现在语法规范中.名为STRING的类型会进一步显示,但不会引用其定义.

鉴于此,我很好奇CPython编译器如何知道注释和文档字符串是什么.这项壮举是如何完成的?

我最初猜测CPython编译器在第一次传递中删除了注释和文档字符串,但随后乞求了help()如何呈现相关文档字符串的问题.

第1节

评论会怎样?

在标记化/词法分析期间,将忽略注释(以#开头的任何内容),因此无需编写规则来解析它们.它们不向解释器/编译器提供任何语义信息,因为它们仅用于为读者提高程序的详细程度,因此它们被忽略.

这是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");

}

这里没有ECHO.所以,没有任何回报.

这是一个有代表性的例子,但python完全相同.

第2节

docstrings会发生什么?

注意:[email protected]��并不意味着复制他在帖子中提供的任何信息.现在,据说,……

I originally guessed that comments and docstrings are removed in a

first pass by the CPython compiler[…]

Docstrings(未分配给任何变量名的字符串文字,’……’,“……”,”’……”或“”“……”“”内的任何内容)确实是处理.它们被解析为简单的字符串文字(STRING标记),正如Martijn Pieters在his answer中提到的那样.截至当前的文档,只是顺便提一下,文档字符串被赋值给函数/ class / module的__doc__属性.如何做到并没有在任何地方深入提及.

实际发生的是它们被标记化并解析为字符串文字,生成的结果解析树将包含它们.从解析树生成字节代码,文档字符串位于__doc__属性中的正确位置(它们不是显式字节代码的一部分,如下所示).我不会详细介绍,因为上面链接的答案描述的内容非常详细.

当然,可以完全忽略它们.如果你使用python -OO(-OO标志代表“强烈优化”,而不是-O代表“温和地优化”),结果字节代码存储在.pyo文件中,这排除了文档字符串.

下图可以看到:

使用以下代码创建文件test.py:

def foo():

""" docstring """

pass

现在,我们将使用正常的标志集编译此代码.

>>> code = compile(open('test.py').read(), '', 'single')

>>> import dis

>>> dis.dis(code)

1 0 LOAD_CONST 0 ()

2 LOAD_CONST 1 ('foo')

4 MAKE_FUNCTION 0

6 STORE_NAME 0 (foo)

8 LOAD_CONST 2 (None)

10 RETURN_VALUE

如您所见,字节代码中没有提到我们的docstring.但是,他们在那里.要获得文档字符串,您可以…

>>> code.co_consts[0].co_consts

(' docstring ', None)

因此,正如您所看到的,docstring确实保留,而不是作为主字节码的一部分.现在,让我们重新编译这段代码,但优化级别设置为2(相当于-OO开关):

>>> code = compile(open('test.py').read(), '', 'single', optimize=2)

>>> dis.dis(code)

1 0 LOAD_CONST 0 ()

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现在已经消失了.

-O和-OO标志只删除内容(字节代码的优化默认完成… -O删除断言语句,如果__debug __:套件来自生成的字节码,而-OO则忽略文档字符串).结果编译时间会略有减少.此外,执行速度保持不变,除非你有大量的assert和if __debug__:语句,否则对性能没有影响.

另外,请记住只有在文档字符串是函数/类/模块定义中的第一个内容时才会保留文档字符串.编译期间只删除所有其他字符串.如果将test.py更改为以下内容:

def foo():

""" docstring """

"""test"""

pass

然后使用optimization = 0重复相同的过程,这在编译时存储在co_consts变量中:

>>> code.co_consts[0].co_consts

(' docstring ', None)

意思是,“”测试“”已被忽略.您会感兴趣的是,此删除操作是字节代码基本优化的一部分.

第3节

补充阅读

(你可能会发现这些引用和我一样有趣.)

> 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()

> dis模块

> peephole.c(Martijn提供) – 所有编译器优化的源代码.如果您能理解它,这尤其令人着迷!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值