Python Ast.Expr类型的Ast解析
关于ast模块正在计算的lineno偏移量,有一些我不理解的地方。通常,当我得到某个ast对象的行号时,它会给出该对象遇到的第一行 例如,在下面的例子中,foo的linPython Ast.Expr类型的Ast解析,python,abstract-syntax-tree,expr,Python,Abstract Syntax Tree,Expr,关于ast模块正在计算的lineno偏移量,有一些我不理解的地方。通常,当我得到某个ast对象的行号时,它会给出该对象遇到的第一行 例如,在下面的例子中,foo的lin st='def foo():\n print "hello"' import ast print ast.parse(st).body[0].lineno print ast.parse(st).body[0].body[0].lineno 函数foo将返回1,hello world打印输出将返回2 但是,如果我分析一
st='def foo():\n print "hello"'
import ast
print ast.parse(st).body[0].lineno
print ast.parse(st).body[0].body[0].lineno
函数foo将返回1,hello world打印输出将返回2
但是,如果我分析一个多行docstring ast.Expr,那么提供的lineno是最后一行
st='def foo():\n """\n Test\n """'
import ast
print ast.parse(st).body[0].lineno
print ast.parse(st).body[0].body[0].lineno
函数的结果仍然是第1行,但docstring的结果是第4行。我希望它在第2行,因为那是docstring开始的时候
我想我要问的是,是否有一种方法可以始终获取所有ast对象(包括ast.Expr)的第一行编号 AST的源位置还有很多需要改进的地方,但其中很多都是由库提供的,库用更有用的位置信息注释AST节点。在您的示例中:
import asttokens
st='def foo():\n """\n Test\n """'
atok = asttokens.ASTTokens(st, parse=True)
print atok.tree.body[0].first_token.start[0]
print atok.tree.body[0].body[0].first_token.start[0]
根据需要打印1和2。也许更有趣的是
print atok.get_text_range(atok.tree.body[0])
print atok.get_text_range(atok.tree.body[0].body[0])
打印与节点相对应的源文本范围:在本例中为0,35和15,35。我很确定它通常不会给出第一行,而是会考虑包含反斜杠、括号和三引号后的第一个虚拟行的一部分的最后一个物理行。换句话说,在异常回溯中看到多行表达式最后一行的规则是一样的,但我怀疑文档中的任何地方都记录了这一点,它只是说这是源文本的行。如果您想深入研究CPython 2.7源代码,它应该在ast.c中设置n_lineno,可能是通过在每个节点类型的一个标头中定义的宏。或者那可能太晚了;您可能需要查看创建CST作为AST输入的生成代码。