2017-02-04 65 views
3

当我使用ast模块解析源代码时,为什么FormattedValue中的Namelineno属性设置为1,即使当f字符串不在线时1?抽象语法树中的Python f字符串的行号

我想知道源代码的哪一行被包含在一个函数定义中,所以我正在步行在FunctionDef节点下方的抽象语法树节点。我将所有lineno属性收集到一个集合中,并告诉我哪些行是功能定义的一部分。

但是,当Python3.6中出现f-strings时,它们以某种方式破坏了这种技术。这里的问题的一个例子:

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}''' 
""" 

回答

4

经过一番研究,似乎F字符串比我意识到的更强大。每一组花括号都不像以前版本的Python中的字典键,它是一个完整的Python代码块。这意味着你可以在这样的大括号写Python表达式:

f'x{y + z}' 

了解这一点,这是有道理的lineno值是括号,而不是字符串中或整个文件中的行号。为了检验这一理论,我想这个代码,并lineno改为3

code = """\ 

f'''x{ 

y}''' 
""" 

如果我刚从FormattedValue节点忽略行号,我的代码再次工作。