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

Don*_*kby 4 python abstract-syntax-tree

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

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

然而,当f-strings出现在 Python 3.6 中时,他们以某种方式打破了这种技术。下面是问题的一个例子:

import ast

code = """\

f'x{y}'
"""

tree = ast.parse(code)

print(ast.dump(tree, include_attributes=True))
Run Code Online (Sandbox Code Playgroud)

这是该脚本的输出:

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)])
Run Code Online (Sandbox Code Playgroud)

我知道这很不可读,所以这里有一些额外的空格相同的输出:

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)])
Run Code Online (Sandbox Code Playgroud)

唯一的源代码在第 2 行,那么这部分输出是什么?

Name(id='y',
     ctx=Load(),
     lineno=1,
     col_offset=1)
Run Code Online (Sandbox Code Playgroud)

我想这可能是行号的字符串,但是当我尝试这一点,但它仍然报告lineno=1

code = """\

f'''

x{y}'''
"""
Run Code Online (Sandbox Code Playgroud)

Don*_*kby 5

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

f'x{y + z}'
Run Code Online (Sandbox Code Playgroud)

有了这种理解,lineno值是大括号内的行号,而不是字符串或整个文件中的行号是有道理的。为了测试该理论,我尝试了此代码,并将其lineno更改为 3。

code = """\

f'''x{

y}'''
"""
Run Code Online (Sandbox Code Playgroud)

如果我只是忽略FormattedValue节点中的行号,我的代码会再次运行。