抽象语法树中Python f字符串的行号

抽象语法树中Python f字符串的行号,python,abstract-syntax-tree,Python,Abstract Syntax Tree,当我使用ast模块解析源代码时,为什么FormattedValue中Name的lineno属性设置为1,即使f字符串不在第1行 我试图查看函数定义中包含哪些源代码行,因此我在FunctionDef节点下面的抽象语法树节点中进行遍历。我将所有lineno属性收集到一个集合中,这告诉我哪些行是函数定义的一部分 然而,当出现在Python3.6中时,他们不知何故打破了这项技术。下面是一个问题示例: import ast code = """\ f'x{y}' """ tree = ast.par

当我使用
ast
模块解析源代码时,为什么
FormattedValue
Name
lineno
属性设置为1,即使f字符串不在第1行

我试图查看函数定义中包含哪些源代码行,因此我在
FunctionDef
节点下面的抽象语法树节点中进行遍历。我将所有
lineno
属性收集到一个集合中,这告诉我哪些行是函数定义的一部分

然而,当出现在Python3.6中时,他们不知何故打破了这项技术。下面是一个问题示例:

import ast

code = """\

f'x{y}'
"""

tree = ast.parse(code)

print(ast.dump(tree, include_attributes=True))
下面是该脚本的输出:

Module(body=[Expr(value=JoinedStr(values=[Str(s='x', lineno=2, col_offset=0), FormattedValue(value=Name(id='y', ctx=Load(), lineno=1, col_offset=1), conversion=-1, format_spec=None, lineno=2, col_offset=0)], lineno=2, col_offset=0), lineno=2, col_offset=0)])
我知道这很难理解,所以这里是相同的输出,带有一些额外的空格:

Module(body=[Expr(value=JoinedStr(values=[
    Str(s='x', lineno=2, col_offset=0), 
    FormattedValue(value=Name(id='y',
                              ctx=Load(),
                              lineno=1,
                              col_offset=1),
                   conversion=-1,
                   format_spec=None,
                   lineno=2,
                   col_offset=0)], lineno=2, col_offset=0), lineno=2, col_offset=0)])
唯一的源代码在第2行,那么输出的这部分是什么呢

Name(id='y',
     ctx=Load(),
     lineno=1,
     col_offset=1)
我认为它可能是字符串中的行号,但当我尝试此操作时,它仍然报告
lineno=1

code = """\

f'''

x{y}'''
"""

经过一些研究,f字串似乎比我想象的更强大。每一组大括号不仅仅是Python早期版本中的一个字典键,它是一个完整的Python代码块。这意味着您可以在大括号中编写Python表达式,如下所示:

f'x{y + z}'
根据这种理解,
lineno
值是大括号中的行号,而不是字符串或整个文件中的行号。为了验证这个理论,我尝试了这个代码,
lineno
改为3

code = """\

f'''x{

y}'''
"""
如果我忽略
FormattedValue
节点中的行号,我的代码会再次工作