2017-02-04 3 views
3

Когда я анализирую исходный код с ast модулем, почему это lineno атрибута Name внутри FormattedValue установлены в 1, даже когда диафрагменная строке не на линии 1?Номер строк из Python F-строк в абстрактном синтаксическом дереве

Я пытаюсь увидеть, какие строки исходного кода включены в определение функции, поэтому я иду узлами абстрактного синтаксического дерева ниже узла FunctionDef. Я собираю все атрибуты lineno в набор, и это говорит мне, какие строки являются частью определения функции.

Однако, когда в Python 3.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 узлов, мой код работает снова.

Смежные вопросы