抽象语法树中 Python 个 f 字符串的行号
Line numbers of Python f-strings in abstract syntax tree
当我使用 ast
模块解析源代码时,为什么 Name
内部 FormattedValue
的 lineno
属性设置为 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))
这是该脚本的输出:
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-strings 比我想象的更强大。每组大括号不仅仅是 Python 以前版本中的一个字典键,它是一个完整的 Python 代码块。这意味着您可以像这样在大括号中编写 Python 表达式:
f'x{y + z}'
根据这种理解,lineno
值是大括号 内的行号 ,而不是字符串或整个文件内的行号。为了验证该理论,我尝试了这段代码,lineno
更改为 3.
code = """\
f'''x{
y}'''
"""
如果我只是忽略来自 FormattedValue
个节点的行号,我的代码将再次运行。
当我使用 ast
模块解析源代码时,为什么 Name
内部 FormattedValue
的 lineno
属性设置为 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))
这是该脚本的输出:
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-strings 比我想象的更强大。每组大括号不仅仅是 Python 以前版本中的一个字典键,它是一个完整的 Python 代码块。这意味着您可以像这样在大括号中编写 Python 表达式:
f'x{y + z}'
根据这种理解,lineno
值是大括号 内的行号 ,而不是字符串或整个文件内的行号。为了验证该理论,我尝试了这段代码,lineno
更改为 3.
code = """\
f'''x{
y}'''
"""
如果我只是忽略来自 FormattedValue
个节点的行号,我的代码将再次运行。