Python 2 tokenize 模块中的换行符

7 投票
3 回答
1306 浏览
提问于 2025-04-18 11:47

我在用Python的tokenize模块,想知道为什么会有两种不同的换行符:

NEWLINE = 4
NL = 54

如果能给我一些代码示例,能同时产生这两种换行符,那就太好了。

3 个回答

1

除了来自文档的引用之外,

NEWLINE这个标记表示Python代码逻辑行的结束;当一行代码在多个物理行上继续时,就会生成NL标记。

这里有一个例子:

def a_func(a, b):
    pass

这将生成:

1,0-1,3:        NAME    'def'
1,4-1,10:       NAME    'a_func'
1,10-1,11:      OP      '('
1,11-1,12:      NAME    'a'
1,12-1,13:      OP      ','
1,14-1,15:      NAME    'b'
1,15-1,16:      OP      ')'
1,16-1,17:      OP      ':'
1,17-1,18:      NEWLINE '\n'
2,0-2,4:        INDENT  '    '
2,4-2,8:        NAME    'pass'
2,8-2,9:        NEWLINE '\n'
3,0-3,0:        DEDENT  ''

def a_func(a,
           b):
    pass

将生成这个:

1,0-1,3:        NAME    'def'
1,4-1,10:       NAME    'a_func'
1,10-1,11:      OP      '('
1,11-1,12:      NAME    'a'
1,12-1,13:      OP      ','
1,13-1,14:      NL      '\n'
2,11-2,12:      NAME    'b'
2,12-2,13:      OP      ')'
2,13-2,14:      OP      ':'
2,14-2,15:      NEWLINE '\n'
3,0-3,4:        INDENT  '    '
3,4-3,8:        NAME    'pass'
3,8-3,9:        NEWLINE '\n'
4,0-4,0:        DEDENT  ''
4,0-4,0:        ENDMARKER       ''

注意在a,后面有1,13-1,14: NL '\n'


简单来说,NEWLINE和NL的区别在于,NL是在一行不“完整”的情况下生成的:

def a_func(a, b):

结果是NEWLINE,因为整个逻辑行在1个物理行上

def another_func(a,
                 b)

结果是NL,因为那1个逻辑行的代码分布在2个物理行上

3

在Python代码中,至少有四种可能出现的换行符'\n'情况,其中有两种是通过特定的标记来表示的:

  1. 结束语句的换行符:tokenize.NEWLINE - 这个标记大致上对应于C或Java中的;符号。

  2. 任何不结束语句的换行符,并且不属于第三或第四种情况:tokenize.NL

  3. 多行字符串中的换行符。

  4. 在行继续符\后出现的换行符 - 与文档中所说的相反,这种情况实际上不会产生任何标记。

因此,以下示例:

# case 1
a = 6
b = 7

# case 2
answer = (
    a * b
)

# case 3
format = """
A multiline string
"""

# case 4
print "something that is continued" \
    "on the following line."

展示了所有可能的情况:

1,0-1,8:        COMMENT '# case 1'
1,8-1,9:        NL      '\n'
2,0-2,1:        NAME    'a'
2,2-2,3:        OP      '='
2,4-2,5:        NUMBER  '6'
2,5-2,6:        NEWLINE '\n'
3,0-3,1:        NAME    'b'
3,2-3,3:        OP      '='
3,4-3,5:        NUMBER  '7'
3,5-3,6:        NEWLINE '\n'
4,0-4,1:        NL      '\n'
5,0-5,8:        COMMENT '# case 2'
5,8-5,9:        NL      '\n'
6,0-6,6:        NAME    'answer'
6,7-6,8:        OP      '='
6,9-6,10:       OP      '('
6,10-6,11:      NL      '\n'
7,4-7,5:        NAME    'a'
7,6-7,7:        OP      '*'
7,8-7,9:        NAME    'b'
7,9-7,10:       NL      '\n'
8,0-8,1:        OP      ')'
8,1-8,2:        NEWLINE '\n'
9,0-9,1:        NL      '\n'
10,0-10,8:      COMMENT '# case 3'
10,8-10,9:      NL      '\n'
11,0-11,6:      NAME    'format'
11,7-11,8:      OP      '='
11,9-13,3:      STRING  '"""\nA multiline string\n"""'
13,3-13,4:      NEWLINE '\n'
14,0-14,1:      NL      '\n'
15,0-15,8:      COMMENT '# case 4'
15,8-15,9:      NL      '\n'
16,0-16,5:      NAME    'print'
16,6-16,35:     STRING  '"something that is continued"'
17,4-17,28:     STRING  '"on the following line."'
17,28-17,29:    NEWLINE '\n'
18,0-18,0:      ENDMARKER       ''
5

根据Python的文档:

tokenize.NL
这个值用来表示一个不结束的换行符。NEWLINE这个标记表示Python代码逻辑行的结束;而NL标记是在一行代码跨越多行物理行时生成的。

更多内容请查看: https://docs.python.org/2/library/tokenize.html

撰写回答