有许多工具可以计算程序中的源代码行数。我现在用的是cloc
。我经常用它来衡量我正在做的项目的复杂性,偶尔会花几个星期的时间来最小化这个度量。然而,这并不理想,因为它受到变量名长度等因素的影响。
grammar = grammar_path.read_text(encoding="UTF-8")
这一行可能有6个令牌,如果我们把第二个参数计算到getattr()
,然后再计算赋值操作符。
我希望在某个地方有这样的实现,我只是不知道该怎么谷歌找到它。如果知道是否有其他语言的现有工具可以做到这一点,那将会很有帮助。
行grammar = grammar_path.read_text(encoding="UTF-8")
有10个标记,如果算上行末尾的NEWLINE
标记,则为11个。使用内置tokenize
标准库模块中的generate_tokens
方法可以很容易地看到这一点。(虽然我在下面的示例中使用的是v3.11,但tokenize
模型从v2.2开始就可用了。不过,生成的令牌的细节已经发生了变化。)
注意,generate_token方法期望它的参数是一个在输入行上迭代的函数。为了进行简单的演示,我只使用sys.stdin.readline
,它从stdin
读取连续的行。更正常的用法是为打开读取的文件提供readline
方法。我在示例中使用enumerate
,以便对连续的令牌进行编号。
$ python3.11
Python 3.11.0 (main, Oct 24 2022, 19:56:01) [GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tokenize
>>> import sys
>>> for i, token in enumerate(tokenize.generate_tokens(sys.stdin.readline), start=1):
... print(f"""{i:3}: {token}""")
...
grammar = grammar_path.read_text(encoding="UTF-8")
1: TokenInfo(type=1 (NAME), string='grammar', start=(1, 0), end=(1, 7), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
2: TokenInfo(type=54 (OP), string='=', start=(1, 8), end=(1, 9), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
3: TokenInfo(type=1 (NAME), string='grammar_path', start=(1, 10), end=(1, 22), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
4: TokenInfo(type=54 (OP), string='.', start=(1, 22), end=(1, 23), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
5: TokenInfo(type=1 (NAME), string='read_text', start=(1, 23), end=(1, 32), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
6: TokenInfo(type=54 (OP), string='(', start=(1, 32), end=(1, 33), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
7: TokenInfo(type=1 (NAME), string='encoding', start=(1, 33), end=(1, 41), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
8: TokenInfo(type=54 (OP), string='=', start=(1, 41), end=(1, 42), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
9: TokenInfo(type=3 (STRING), string='"UTF-8"', start=(1, 42), end=(1, 49), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
10: TokenInfo(type=54 (OP), string=')', start=(1, 49), end=(1, 50), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
11: TokenInfo(type=4 (NEWLINE), string='n', start=(1, 50), end=(1, 51), line='grammar = grammar_path.read_text(encoding="UTF-8")n')
此时,循环正在等待下一行;为了终止循环,我需要输入一个输入结束标记(在Unix上是Control-D;Windows上的Control-Z;在这两种情况下,都按Enter)。然后标记器将返回一个最终的ENDMARKER
标记:
12: TokenInfo(type=0 (ENDMARKER), string='', start=(2, 0), end=(2, 0), line='')
如文档中所述,您还可以使用标准库模块作为命令行实用程序来列出令牌。同样,我必须通过键入输入结束标记来终止输入,在此之后打印最后一行:
$ python3.11 -m tokenize
grammar = grammar_path.read_text(encoding="UTF-8")
1,0-1,7: NAME 'grammar'
1,8-1,9: OP '='
1,10-1,22: NAME 'grammar_path'
1,22-1,23: OP '.'
1,23-1,32: NAME 'read_text'
1,32-1,33: OP '('
1,33-1,41: NAME 'encoding'
1,41-1,42: OP '='
1,42-1,49: STRING '"UTF-8"'
1,49-1,50: OP ')'
1,50-1,51: NEWLINE 'n'
2,0-2,0: ENDMARKER ''