标记化modu的奇怪行为

2024-04-29 17:00:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我在使用tokenize模块时看到一些奇怪的行为

import tokenize, io, sys
from contextlib import closing
source=u"""
for i in range(10):
    print "HELLO"
    if i==5:
        print "bingo"
"""
def parse():
    with closing(io.StringIO(source)) as f:
        for type, token, (srow, scol), (erow, ecol), line in tokenize.generate_tokens(f.readline):
            print("%d,%d-%d,%d:\t%s\t%s" % (srow, scol, erow, ecol, tokenize.tok_name[type], repr(token)))
            yield type, token, (srow, scol), (erow, ecol), line

for token in tokenize.untokenize(parse()):
    sys.stdout.write(token)

控制台输出中缺少if前面的缩进。Python2和Python3都会这样。 这是一个已知的错误还是我用错了模块?你知道吗

3,1-3,6:    NAME    u'print'
3,7-3,14:   STRING  u'"HELLO"'
3,14-3,15:  NEWLINE u'\n'
4,1-4,3:    NAME    u'if'
4,4-4,5:    NAME    u'i'
4,5-4,7:    OP  u'=='

我用制表符做缩进。当我用4个空格替换制表符时,我得到了正确的结果

3,4-3,9:    NAME    u'print'
3,10-3,17:  STRING  u'"HELLO"'
3,17-3,18:  NEWLINE u'\n'
4,4-4,6:    NAME    u'if'
4,7-4,8:    NAME    u'i'
4,8-4,10:   OP  u'=='
4,10-4,11:  NUMBER  u'5'
4,11-4,12:  OP  u':'

区别在于if的起始列,当使用制表符时为1,当使用空格时为4。 这似乎是“untokenize”函数中的一个bug,它似乎输出空格而不是制表符。你知道吗

有人能证实吗?你知道吗


Tags: nameintokenhelloforiftype制表符
1条回答
网友
1楼 · 发布于 2024-04-29 17:00:45

一切都是应该的。列索引基于0。一个tab是一个字符,因此if在列1中被正确检测。当您将此tab更改为4 spaces时,确实有4个字符,因此if在第4列中被检测到。
代码输出的证明:

1,0-1,1:    NL  u'\n'
2,0-2,3:    NAME    u'for'

如您所见,第一行的linefeed和第二行的for都在第0列中。
您可能会感到困惑,因为行号是以1为基础的。你知道吗

脚注:缩进应该使用空格。这是一个确保在另一个开发人员的机器上一致显示缩进的约定。显示的标签宽度可以调整,空格宽度只有一个字符。

编辑:
在OP提出tokenizeuntokenize存在问题的意见后,我必须添加以下注释。
作为official documentation says
结果保证标记化回与输入匹配,这样转换是无损的并且往返是有保证的。保证仅适用于令牌类型和令牌字符串,因为令牌之间的间距(列位置)可能会改变。

相关问题 更多 >