Документация Python неофициальный перевод
Содержание страницы

ast – абстрактные синтаксические деревьяast – Abstract Syntax Trees

Исходный код: Lib/ast.py


Модуль ast помогает приложениям Python обрабатывать деревья абстрактного синтаксиса языка Python. Абстрактный синтаксис может меняться от версии к версии; с помощью этого модуля можно программно узнать, как выглядит текущая грамматика.

Абстрактное синтаксическое дерево можно создать, передав ast.PyCF_ONLY_AST в качестве флага встроенной функции compile() или используя вспомогательную функцию parse() из этого модуля. Результатом будет дерево объектов, классы которых наследуют от ast.AST. Абстрактное синтаксическое дерево можно скомпилировать в объект кода Python с помощью встроенной функции compile().

Абстрактная грамматикаAbstract Grammar

Абстрактная грамматика в настоящее время определяется следующим образом:

-- Встроенные типы ASDL:
-- идентификатор, целое, строка, константа

module Python
{
    mod = Module(stmt* body, type_ignore* type_ignores)
        | Interactive(stmt* body)
        | Expression(expr body)
        | FunctionType(expr* argtypes, expr returns)

    stmt = FunctionDef(identifier name, arguments args,
                       stmt* body, expr* decorator_list, expr? returns,
                       string? type_comment)
          | AsyncFunctionDef(identifier name, arguments args,
                             stmt* body, expr* decorator_list, expr? returns,
                             string? type_comment)

          | ClassDef(identifier name,
             expr* bases,
             keyword* keywords,
             stmt* body,
             expr* decorator_list)
          | Return(expr? value)

          | Delete(expr* targets)
          | Assign(expr* targets, expr value, string? type_comment)
          | AugAssign(expr target, operator op, expr value)
          -- 'simple' указывает, что аннотируется простое имя без скобок
          | AnnAssign(expr target, expr annotation, expr? value, int simple)

          -- используется 'orelse', так как else – ключевое слово в целевых языках
          | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
          | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
          | While(expr test, stmt* body, stmt* orelse)
          | If(expr test, stmt* body, stmt* orelse)
          | With(withitem* items, stmt* body, string? type_comment)
          | AsyncWith(withitem* items, stmt* body, string? type_comment)

          | Raise(expr? exc, expr? cause)
          | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
          | Assert(expr test, expr? msg)

          | Import(alias* names)
          | ImportFrom(identifier? module, alias* names, int? level)

          | Global(identifier* names)
          | Nonlocal(identifier* names)
          | Expr(expr value)
          | Pass | Break | Continue

          -- col_offset – это смещение в байтах в строке UTF-8, используемой парсером
          attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

          -- BoolOp() может использовать left и right?
    expr = BoolOp(boolop op, expr* values)
         | NamedExpr(expr target, expr value)
         | BinOp(expr left, operator op, expr right)
         | UnaryOp(unaryop op, expr operand)
         | Lambda(arguments args, expr body)
         | IfExp(expr test, expr body, expr orelse)
         | Dict(expr* keys, expr* values)
         | Set(expr* elts)
         | ListComp(expr elt, comprehension* generators)
         | SetComp(expr elt, comprehension* generators)
         | DictComp(expr key, expr value, comprehension* generators)
         | GeneratorExp(expr elt, comprehension* generators)
         -- грамматика ограничивает, где могут встречаться выражения yield
         | Await(expr value)
         | Yield(expr? value)
         | YieldFrom(expr value)
         -- нужны последовательности для сравнения, чтобы различать
         -- x < 4 < 3 and (x < 4) < 3
         | Compare(expr left, cmpop* ops, expr* comparators)
         | Call(expr func, expr* args, keyword* keywords)
         | FormattedValue(expr value, int? conversion, expr? format_spec)
         | JoinedStr(expr* values)
         | Constant(constant value, string? kind)

         -- следующее выражение может появляться в контексте присваивания
         | Attribute(expr value, identifier attr, expr_context ctx)
         | Subscript(expr value, expr slice, expr_context ctx)
         | Starred(expr value, expr_context ctx)
         | Name(identifier id, expr_context ctx)
         | List(expr* elts, expr_context ctx)
         | Tuple(expr* elts, expr_context ctx)

         -- может встречаться только в Subscript
         | Slice(expr? lower, expr? upper, expr? step)

          -- col_offset – это смещение в байтах в строке UTF-8, используемой парсером
          attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    expr_context = Load | Store | Del

    boolop = And | Or

    operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
                 | RShift | BitOr | BitXor | BitAnd | FloorDiv

    unaryop = Invert | Not | UAdd | USub

    cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn

    comprehension = (expr target, expr iter, expr* ifs, int is_async)

    excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
                    attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
                 expr* kw_defaults, arg? kwarg, expr* defaults)

    arg = (identifier arg, expr? annotation, string? type_comment)
           attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    -- ключевые аргументы, переданные вызову (идентификатор NULL для **kwargs)
    keyword = (identifier? arg, expr value)
               attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    -- имя импорта с необязательным псевдонимом 'as'
    alias = (identifier name, identifier? asname)

    withitem = (expr context_expr, expr? optional_vars)

    type_ignore = TypeIgnore(int lineno, string tag)
}

Классы узловNode classes

class ast.AST

Это базовый класс всех узлов AST. Конкретные классы узлов порождаются из файла Parser/Python.asdl, который воспроизведён ниже. Они определены в C-модуле _ast и реэкспортированы в ast.

Для каждого символа левой части абстрактной грамматики определён один класс (например, ast.stmt или ast.expr). Кроме того, для каждого конструктора правой части определён один класс; эти классы наследуют от классов для деревьев левой части. Например, ast.BinOp наследует от ast.expr. Для продукционных правил с альтернативами (так называемых «сумм») класс левой части является абстрактным: создаются только экземпляры конкретных узлов-конструкторов.

_fields

Каждый конкретный класс имеет атрибут _fields, который содержит имена всех дочерних узлов.

Каждый экземпляр конкретного класса имеет по одному атрибуту для каждого дочернего узла, тип которого определён в грамматике. Например, экземпляры ast.BinOp имеют атрибут left типа ast.expr.

Если эти атрибуты помечены как необязательные в грамматике (с помощью вопросительного знака), значением может быть None. Если атрибуты могут иметь ноль или более значений (помечены звёздочкой), значения представляются в виде списков Python. Все возможные атрибуты должны присутствовать и иметь корректные значения при компиляции AST с помощью compile().

lineno
col_offset
end_lineno
end_col_offset

Экземпляры подклассов ast.expr и ast.stmt имеют атрибуты lineno, col_offset, end_lineno и end_col_offset. lineno и end_lineno – это номера первой и последней строк фрагмента исходного текста (нумерация с 1, то есть первая строка – строка 1), а col_offset и end_col_offset – соответствующие смещения в байтах UTF-8 для первого и последнего токенов, породивших узел. Смещение в UTF-8 записывается, потому что парсер использует UTF-8 внутри.

Обратите внимание, что конечные позиции не требуются компилятором и поэтому являются необязательными. Смещение конца находится после последнего символа, например, можно получить фрагмент исходного кода узла выражения из одной строки с помощью source_line[node.col_offset : node.end_col_offset].

Конструктор класса ast.T разбирает свои аргументы следующим образом:

  • Если есть позиционные аргументы, их должно быть столько же, сколько элементов в T._fields; они будут присвоены как атрибуты с этими именами.

  • Если есть ключевые аргументы, они установят атрибуты с теми же именами в указанные значения.

Например, чтобы создать и заполнить узел ast.UnaryOp, можно использовать

node = ast.UnaryOp()
node.op = ast.USub()
node.operand = ast.Constant()
node.operand.value = 5
node.operand.lineno = 0
node.operand.col_offset = 0
node.lineno = 0
node.col_offset = 0

или более компактный

node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
                   lineno=0, col_offset=0)

Изменено в версии 3.8: Класс ast.Constant теперь используется для всех констант.

Изменено в версии 3.9: Простые индексы представляются своим значением, расширенные срезы представляются кортежами.

Устарело с версии 3.8: Старые классы ast.Num, ast.Str, ast.Bytes, ast.NameConstant и ast.Ellipsis всё ещё доступны, но будут удалены в будущих версиях Python. А пока их создание будет возвращать экземпляр другого класса.

Устарело с версии 3.9: Старые классы ast.Index и ast.ExtSlice всё ещё доступны, но будут удалены в будущих выпусках Python. При этом при их создании будет возвращён экземпляр другого класса.

Примечание

Описания конкретных классов узлов, приведённые здесь, изначально были адаптированы из замечательного проекта Green Tree Snakes и всех его участников.

ЛитералыLiterals

class ast.Constant(value)

Постоянное значение. Атрибут value литерала Constant содержит объект Python, который он представляет. Представленные значения могут быть простыми типами, такими как число, строка или None, а также неизменяемыми контейнерными типами (кортежами и замороженными множествами), если все их элементы постоянны.

>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4))
Expression(
    body=Constant(value=123))
class ast.FormattedValue(value, conversion, format_spec)

Узел, представляющий одно поле форматирования в f-строке. Если строка содержит только одно поле форматирования и больше ничего, узел может быть изолированным; в противном случае он встречается внутри JoinedStr.

  • value – это любой узел выражения (например, литерал, переменная или вызов функции).

  • conversion – целое число:

    • -1: без форматирования

    • 115: !s форматирование строк

    • 114: !r форматирование repr

    • 97: !a форматирование ascii

  • format_spec – узел JoinedStr, представляющий форматирование значения, или None, если формат не указан. conversion и format_spec могут быть установлены одновременно.

class ast.JoinedStr(values)

F-строка, содержащая последовательность FormattedValue и Constant узлов.

>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4))
Expression(
    body=JoinedStr(
        values=[
            Constant(value='sin('),
            FormattedValue(
                value=Name(id='a', ctx=Load()),
                conversion=-1),
            Constant(value=') is '),
            FormattedValue(
                value=Call(
                    func=Name(id='sin', ctx=Load()),
                    args=[
                        Name(id='a', ctx=Load())],
                    keywords=[]),
                conversion=-1,
                format_spec=JoinedStr(
                    values=[
                        Constant(value='.3')]))]))
class ast.List(elts, ctx)
class ast.Tuple(elts, ctx)

Список или кортеж. elts содержит список узлов, представляющих элементы. ctx равен Store, если контейнер является целью присваивания (т.е. (x,y)=something), и Load в противном случае.

>>> print(ast.dump(ast.parse('[1, 2, 3]', mode='eval'), indent=4))
Expression(
    body=List(
        elts=[
            Constant(value=1),
            Constant(value=2),
            Constant(value=3)],
        ctx=Load()))
>>> print(ast.dump(ast.parse('(1, 2, 3)', mode='eval'), indent=4))
Expression(
    body=Tuple(
        elts=[
            Constant(value=1),
            Constant(value=2),
            Constant(value=3)],
        ctx=Load()))
class ast.Set(elts)

Множество. elts содержит список узлов, представляющих элементы множества.

>>> print(ast.dump(ast.parse('{1, 2, 3}', mode='eval'), indent=4))
Expression(
    body=Set(
        elts=[
            Constant(value=1),
            Constant(value=2),
            Constant(value=3)]))
class ast.Dict(keys, values)

Словарь. keys и values содержат списки узлов, представляющих ключи и значения соответственно, в соответствующем порядке (то, что было бы возвращено при вызове dictionary.keys() и dictionary.values()).

При распаковке словаря с помощью литералов словаря выражение, которое нужно раскрыть, помещается в список values, а None – на соответствующую позицию в keys.

>>> print(ast.dump(ast.parse('{"a":1, **d}', mode='eval'), indent=4))
Expression(
    body=Dict(
        keys=[
            Constant(value='a'),
            None],
        values=[
            Constant(value=1),
            Name(id='d', ctx=Load())]))

ПеременныеVariables

class ast.Name(id, ctx)

Имя переменной. id содержит имя в виде строки, а ctx – один из следующих типов.

class ast.Load
class ast.Store
class ast.Del

Ссылки на переменные можно использовать для загрузки значения переменной, для присваивания ей нового значения или для её удаления. Ссылки на переменные получают контекст, чтобы различать эти случаи.

>>> print(ast.dump(ast.parse('a'), indent=4))
Module(
    body=[
        Expr(
            value=Name(id='a', ctx=Load()))],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a = 1'), indent=4))
Module(
    body=[
        Assign(
            targets=[
                Name(id='a', ctx=Store())],
            value=Constant(value=1))],
    type_ignores=[])

>>> print(ast.dump(ast.parse('del a'), indent=4))
Module(
    body=[
        Delete(
            targets=[
                Name(id='a', ctx=Del())])],
    type_ignores=[])
class ast.Starred(value, ctx)

Ссылка на переменную *var. В value хранится переменная, обычно узел Name. Этот тип необходимо использовать при построении узла Call с помощью *args.

>>> print(ast.dump(ast.parse('a, *b = it'), indent=4))
Module(
    body=[
        Assign(
            targets=[
                Tuple(
                    elts=[
                        Name(id='a', ctx=Store()),
                        Starred(
                            value=Name(id='b', ctx=Store()),
                            ctx=Store())],
                    ctx=Store())],
            value=Name(id='it', ctx=Load()))],
    type_ignores=[])

ВыраженияExpressions

class ast.Expr(value)

Когда выражение, например вызов функции, выступает в роли самостоятельного оператора и его возвращаемое значение не используется и не сохраняется, оно помещается в этот контейнер. value содержит один из остальных узлов этого раздела: узел Constant, узел Name, Lambda, Yield или YieldFrom.

>>> print(ast.dump(ast.parse('-a'), indent=4))
Module(
    body=[
        Expr(
            value=UnaryOp(
                op=USub(),
                operand=Name(id='a', ctx=Load())))],
    type_ignores=[])
class ast.UnaryOp(op, operand)

Унарная операция. op – оператор, а operand – любой узел выражения.

class ast.UAdd
class ast.USub
class ast.Not
class ast.Invert

Токены унарных операторов. Not – ключевое слово not, Invert – оператор ~.

>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4))
Expression(
    body=UnaryOp(
        op=Not(),
        operand=Name(id='x', ctx=Load())))
class ast.BinOp(left, op, right)

Бинарная операция (например, сложение или деление). op – оператор, а left и right – любые узлы выражений.

>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4))
Expression(
    body=BinOp(
        left=Name(id='x', ctx=Load()),
        op=Add(),
        right=Name(id='y', ctx=Load())))
class ast.Add
class ast.Sub
class ast.Mult
class ast.Div
class ast.FloorDiv
class ast.Mod
class ast.Pow
class ast.LShift
class ast.RShift
class ast.BitOr
class ast.BitXor
class ast.BitAnd
class ast.MatMult

Токены бинарных операторов.

class ast.BoolOp(op, values)

Логическая операция – 'or' или 'and'. op – это Or или And. values – участвующие значения. Последовательные операции с одним и тем же оператором, например a or b or c, сводятся в один узел с несколькими значениями.

Это не включает not, который является UnaryOp.

>>> print(ast.dump(ast.parse('x or y', mode='eval'), indent=4))
Expression(
    body=BoolOp(
        op=Or(),
        values=[
            Name(id='x', ctx=Load()),
            Name(id='y', ctx=Load())]))
class ast.And
class ast.Or

Токены логических операторов.

class ast.Compare(left, ops, comparators)

Сравнение двух или более значений. left – первое значение в сравнении, ops – список операторов, а comparators – список значений после первого элемента сравнения.

>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4))
Expression(
    body=Compare(
        left=Constant(value=1),
        ops=[
            LtE(),
            Lt()],
        comparators=[
            Name(id='a', ctx=Load()),
            Constant(value=10)]))
class ast.Eq
class ast.NotEq
class ast.Lt
class ast.LtE
class ast.Gt
class ast.GtE
class ast.Is
class ast.IsNot
class ast.In
class ast.NotIn

Токены операторов сравнения.

class ast.Call(func, args, keywords, starargs, kwargs)

Вызов функции. func – это функция; обычно это объект Name или Attribute. Об аргументах:

  • args содержит список аргументов, переданных по позиции.

  • keywords содержит список объектов keyword, представляющих аргументы, переданные по ключевому слову.

При создании узла Call, args и keywords обязательны, но они могут быть пустыми списками. starargs и kwargs необязательны.

>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4))
Expression(
    body=Call(
        func=Name(id='func', ctx=Load()),
        args=[
            Name(id='a', ctx=Load()),
            Starred(
                value=Name(id='d', ctx=Load()),
                ctx=Load())],
        keywords=[
            keyword(
                arg='b',
                value=Name(id='c', ctx=Load())),
            keyword(
                value=Name(id='e', ctx=Load()))]))
class ast.keyword(arg, value)

Именованный аргумент вызова функции или определения класса. arg – это необработанная строка с именем параметра, value – узел, который нужно передать.

class ast.IfExp(test, body, orelse)

Выражение, например a if b else c. Каждое поле содержит один узел, поэтому в следующем примере все три являются узлами Name.

>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4))
Expression(
    body=IfExp(
        test=Name(id='b', ctx=Load()),
        body=Name(id='a', ctx=Load()),
        orelse=Name(id='c', ctx=Load())))
class ast.Attribute(value, attr, ctx)

Доступ к атрибуту, например d.keys. value – это узел, обычно Name. attr – это строка с именем атрибута, а ctxLoad, Store или Del в зависимости от того, как используется атрибут.

>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4))
Expression(
    body=Attribute(
        value=Name(id='snake', ctx=Load()),
        attr='colour',
        ctx=Load()))
class ast.NamedExpr(target, value)

Именованное выражение. Этот узел AST создаётся оператором присваивания (также известным как оператор «морж»). В отличие от узла Assign, где первый аргумент может быть несколькими узлами, в данном случае и target, и value должны быть одиночными узлами.

>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4))
Expression(
    body=NamedExpr(
        target=Name(id='x', ctx=Store()),
        value=Constant(value=4)))

ИндексированиеSubscripting

class ast.Subscript(value, slice, ctx)

Индексация, такая как l[1]. value – индексируемый объект (обычно последовательность или отображение). slice – это индекс, срез или ключ. Оно может быть Tuple и содержать Slice. ctx является Load, Store или Del в зависимости от выполняемого действия при индексации.

>>> print(ast.dump(ast.parse('l[1:2, 3]', mode='eval'), indent=4))
Expression(
    body=Subscript(
        value=Name(id='l', ctx=Load()),
        slice=Tuple(
            elts=[
                Slice(
                    lower=Constant(value=1),
                    upper=Constant(value=2)),
                Constant(value=3)],
            ctx=Load()),
        ctx=Load()))
class ast.Slice(lower, upper, step)

Обычный срез (в виде lower:upper или lower:upper:step). Может встречаться только внутри поля slice узла Subscript, либо напрямую, либо как элемент Tuple.

>>> print(ast.dump(ast.parse('l[1:2]', mode='eval'), indent=4))
Expression(
    body=Subscript(
        value=Name(id='l', ctx=Load()),
        slice=Slice(
            lower=Constant(value=1),
            upper=Constant(value=2)),
        ctx=Load()))

Генераторы коллекцийComprehensions

class ast.ListComp(elt, generators)
class ast.SetComp(elt, generators)
class ast.GeneratorExp(elt, generators)
class ast.DictComp(key, value, generators)

Генераторы списков и множеств, генераторные выражения и генераторы словарей. elt (или key и value) – это один узел, представляющий часть, которая будет вычисляться для каждого элемента.

generators – это список узлов comprehension.

>>> print(ast.dump(ast.parse('[x for x in numbers]', mode='eval'), indent=4))
Expression(
    body=ListComp(
        elt=Name(id='x', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                ifs=[],
                is_async=0)]))
>>> print(ast.dump(ast.parse('{x: x**2 for x in numbers}', mode='eval'), indent=4))
Expression(
    body=DictComp(
        key=Name(id='x', ctx=Load()),
        value=BinOp(
            left=Name(id='x', ctx=Load()),
            op=Pow(),
            right=Constant(value=2)),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                ifs=[],
                is_async=0)]))
>>> print(ast.dump(ast.parse('{x for x in numbers}', mode='eval'), indent=4))
Expression(
    body=SetComp(
        elt=Name(id='x', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                ifs=[],
                is_async=0)]))
class ast.comprehension(target, iter, ifs, is_async)

Одно предложение for в генераторе коллекции. target – это ссылка, используемая для каждого элемента (обычно узел Name или Tuple). iter – объект, по которому выполняется итерация. ifs – список проверочных выражений: каждое предложение for может содержать несколько ifs.

is_async указывает, что генератор коллекции является асинхронным (использует async for вместо for). Значение – целое число (0 или 1).

>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'),
...                indent=4)) # несколько включений в одном
Expression(
    body=ListComp(
        elt=Call(
            func=Name(id='ord', ctx=Load()),
            args=[
                Name(id='c', ctx=Load())],
            keywords=[]),
        generators=[
            comprehension(
                target=Name(id='line', ctx=Store()),
                iter=Name(id='file', ctx=Load()),
                ifs=[],
                is_async=0),
            comprehension(
                target=Name(id='c', ctx=Store()),
                iter=Name(id='line', ctx=Load()),
                ifs=[],
                is_async=0)]))

>>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'),
...                indent=4)) # выражение-генератор
Expression(
    body=GeneratorExp(
        elt=BinOp(
            left=Name(id='n', ctx=Load()),
            op=Pow(),
            right=Constant(value=2)),
        generators=[
            comprehension(
                target=Name(id='n', ctx=Store()),
                iter=Name(id='it', ctx=Load()),
                ifs=[
                    Compare(
                        left=Name(id='n', ctx=Load()),
                        ops=[
                            Gt()],
                        comparators=[
                            Constant(value=5)]),
                    Compare(
                        left=Name(id='n', ctx=Load()),
                        ops=[
                            Lt()],
                        comparators=[
                            Constant(value=10)])],
                is_async=0)]))

>>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'),
...                indent=4)) # асинхронное включение
Expression(
    body=ListComp(
        elt=Name(id='i', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='i', ctx=Store()),
                iter=Name(id='soc', ctx=Load()),
                ifs=[],
                is_async=1)]))

ИнструкцииStatements

class ast.Assign(targets, value, type_comment)

Присваивание. targets – список узлов, а value – один узел.

Несколько узлов в targets обозначают присваивание одного и того же значения каждому. Распаковка представляется помещением узла Tuple или List внутрь targets.

type_comment

type_comment – это необязательная строка с аннотацией типа в виде комментария.

>>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # множественное присваивание
Module(
    body=[
        Assign(
            targets=[
                Name(id='a', ctx=Store()),
                Name(id='b', ctx=Store())],
            value=Constant(value=1))],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # распаковка
Module(
    body=[
        Assign(
            targets=[
                Tuple(
                    elts=[
                        Name(id='a', ctx=Store()),
                        Name(id='b', ctx=Store())],
                    ctx=Store())],
            value=Name(id='c', ctx=Load()))],
    type_ignores=[])
class ast.AnnAssign(target, annotation, value, simple)

Присваивание с аннотацией типа. target – это один узел, которым может быть Name, Attribute или Subscript. annotation – это аннотация, например узел Constant или Name. value – единственный необязательный узел. simple – целое число-флаг, равное True для узла Name в target, которые не появляются в круглых скобках и поэтому являются чистыми именами, а не выражениями.

>>> print(ast.dump(ast.parse('c: int'), indent=4))
Module(
    body=[
        AnnAssign(
            target=Name(id='c', ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            simple=1)],
    type_ignores=[])

>>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # аннотация со скобками
Module(
    body=[
        AnnAssign(
            target=Name(id='a', ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            value=Constant(value=1),
            simple=0)],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # аннотация атрибута
Module(
    body=[
        AnnAssign(
            target=Attribute(
                value=Name(id='a', ctx=Load()),
                attr='b',
                ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            simple=0)],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # аннотация подписки
Module(
    body=[
        AnnAssign(
            target=Subscript(
                value=Name(id='a', ctx=Load()),
                slice=Constant(value=1),
                ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            simple=0)],
    type_ignores=[])
class ast.AugAssign(target, op, value)

Расширенное присваивание, например a += 1. В следующем примере target – это узел Имя для x (с контекстом Store), op – это Сложение, а value – это Константа со значением 1.

Атрибут target не может быть класса Tuple или List, в отличие от целей Assign.

>>> print(ast.dump(ast.parse('x += 2'), indent=4))
Module(
    body=[
        AugAssign(
            target=Name(id='x', ctx=Store()),
            op=Add(),
            value=Constant(value=2))],
    type_ignores=[])
class ast.Raise(exc, cause)

Инструкция raise. exc – объект исключения, который необходимо возбудить, обычно Вызов или Имя, или None для отдельного raise. cause – необязательная часть для y в Возбуждение.

>>> print(ast.dump(ast.parse('raise x from y'), indent=4))
Module(
    body=[
        Raise(
            exc=Name(id='x', ctx=Load()),
            cause=Name(id='y', ctx=Load()))],
    type_ignores=[])
class ast.Assert(test, msg)

Утверждение. test содержит условие, например узел Compare. msg содержит сообщение об ошибке.

>>> print(ast.dump(ast.parse('assert x,y'), indent=4))
Module(
    body=[
        Assert(
            test=Name(id='x', ctx=Load()),
            msg=Name(id='y', ctx=Load()))],
    type_ignores=[])
class ast.Delete(targets)

Представляет инструкцию del. targets – список узлов, например узлов Name, Attribute или Subscript.

>>> print(ast.dump(ast.parse('del x,y,z'), indent=4))
Module(
    body=[
        Delete(
            targets=[
                Name(id='x', ctx=Del()),
                Name(id='y', ctx=Del()),
                Name(id='z', ctx=Del())])],
    type_ignores=[])
class ast.Pass

Инструкция pass.

>>> print(ast.dump(ast.parse('pass'), indent=4))
Module(
    body=[
        Pass()],
    type_ignores=[])

Другие инструкции, которые применимы только внутри функций или циклов, описаны в других разделах.

ИмпортыImports

class ast.Import(names)

Инструкция импорта. names – это список узлов alias.

>>> print(ast.dump(ast.parse('import x,y,z'), indent=4))
Module(
    body=[
        Import(
            names=[
                alias(name='x'),
                alias(name='y'),
                alias(name='z')])],
    type_ignores=[])
class ast.ImportFrom(module, names, level)

Представляет from x import y. module – это необработанная строка имени from, без начальных точек, или None для инструкций вроде from . import foo. level – целое число, указывающее уровень относительного импорта (0 означает абсолютный импорт).

>>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4))
Module(
    body=[
        ImportFrom(
            module='y',
            names=[
                alias(name='x'),
                alias(name='y'),
                alias(name='z')],
            level=0)],
    type_ignores=[])
class ast.alias(name, asname)

Оба параметра – необработанные строки имён. asname может быть None, если должно использоваться обычное имя.

>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4))
Module(
    body=[
        ImportFrom(
            module='foo.bar',
            names=[
                alias(name='a', asname='b'),
                alias(name='c')],
            level=2)],
    type_ignores=[])

Управление потокомControl flow

Примечание

Необязательные предложения, такие как else, сохраняются как пустой список, если они отсутствуют.

class ast.If(test, body, orelse)

Инструкция if. test содержит один узел, например узел Compare. body и orelse содержат по списку узлов.

Предложения elif не имеют специального представления в AST, а появляются как дополнительные узлы If в разделе orelse предыдущего.

>>> print(ast.dump(ast.parse("""
... if x:
...    ...
... elif y:
...    ...
... else:
...    ...
... """), indent=4))
Module(
    body=[
        If(
            test=Name(id='x', ctx=Load()),
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            orelse=[
                If(
                    test=Name(id='y', ctx=Load()),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))],
                    orelse=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])
class ast.For(target, iter, body, orelse, type_comment)

Цикл for. target содержит переменную (или переменные), которой присваивает цикл, в виде одного узла Name, Tuple или List. iter содержит элемент, по которому выполняется итерация, также в виде одного узла. body и orelse содержат списки узлов для выполнения. Узлы в orelse выполняются, если цикл завершается нормально, а не через оператор break.

type_comment

type_comment – это необязательная строка с аннотацией типа в виде комментария.

>>> print(ast.dump(ast.parse("""
... for x in y:
...     ...
... else:
...     ...
... """), indent=4))
Module(
    body=[
        For(
            target=Name(id='x', ctx=Store()),
            iter=Name(id='y', ctx=Load()),
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            orelse=[
                Expr(
                    value=Constant(value=Ellipsis))])],
    type_ignores=[])
class ast.While(test, body, orelse)

Цикл while. test содержит условие, например узел Compare.

>> print(ast.dump(ast.parse("""
... while x:
...    ...
... else:
...    ...
... """), indent=4))
Module(
    body=[
        While(
            test=Name(id='x', ctx=Load()),
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            orelse=[
                Expr(
                    value=Constant(value=Ellipsis))])],
    type_ignores=[])
class ast.Break
class ast.Continue

Инструкции break и continue.

>>> print(ast.dump(ast.parse("""\
... for a in b:
...     if a > 5:
...         break
...     else:
...         continue
...
... """), indent=4))
Module(
    body=[
        For(
            target=Name(id='a', ctx=Store()),
            iter=Name(id='b', ctx=Load()),
            body=[
                If(
                    test=Compare(
                        left=Name(id='a', ctx=Load()),
                        ops=[
                            Gt()],
                        comparators=[
                            Constant(value=5)]),
                    body=[
                        Break()],
                    orelse=[
                        Continue()])],
            orelse=[])],
    type_ignores=[])
class ast.Try(body, handlers, orelse, finalbody)

Блоки try. Все атрибуты – списки узлов для выполнения, за исключением handlers, который является списком узлов ExceptHandler.

>>> print(ast.dump(ast.parse("""
... try:
...    ...
... except Exception:
...    ...
... except OtherException as e:
...    ...
... else:
...    ...
... finally:
...    ...
... """), indent=4))
Module(
    body=[
        Try(
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            handlers=[
                ExceptHandler(
                    type=Name(id='Exception', ctx=Load()),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                ExceptHandler(
                    type=Name(id='OtherException', ctx=Load()),
                    name='e',
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])],
            orelse=[
                Expr(
                    value=Constant(value=Ellipsis))],
            finalbody=[
                Expr(
                    value=Constant(value=Ellipsis))])],
    type_ignores=[])
class ast.ExceptHandler(type, name, body)

Одно предложение except. type – тип исключения, который оно перехватывает, обычно узел Name (или None для универсального предложения except:). name – необработанная строка для имени, в котором будет сохранено исключение, или None, если в предложении нет as foo. body – список узлов.

>>> print(ast.dump(ast.parse("""\
... try:
...     a + 1
... except TypeError:
...     pass
... """), indent=4))
Module(
    body=[
        Try(
            body=[
                Expr(
                    value=BinOp(
                        left=Name(id='a', ctx=Load()),
                        op=Add(),
                        right=Constant(value=1)))],
            handlers=[
                ExceptHandler(
                    type=Name(id='TypeError', ctx=Load()),
                    body=[
                        Pass()])],
            orelse=[],
            finalbody=[])],
    type_ignores=[])
class ast.With(items, body, type_comment)

Блок with. items – это список узлов withitem, представляющих менеджеры контекста, а body – это блок с отступом внутри контекста.

type_comment

type_comment – это необязательная строка с аннотацией типа в виде комментария.

class ast.withitem(context_expr, optional_vars)

Один менеджер контекста в блоке with. context_expr – это менеджер контекста, часто узел Call. optional_vars – это Name, Tuple или List для части as foo, или None, если она не используется.

>>> print(ast.dump(ast.parse("""\
... with a as b, c as d:
...    something(b, d)
... """), indent=4))
Module(
    body=[
        With(
            items=[
                withitem(
                    context_expr=Name(id='a', ctx=Load()),
                    optional_vars=Name(id='b', ctx=Store())),
                withitem(
                    context_expr=Name(id='c', ctx=Load()),
                    optional_vars=Name(id='d', ctx=Store()))],
            body=[
                Expr(
                    value=Call(
                        func=Name(id='something', ctx=Load()),
                        args=[
                            Name(id='b', ctx=Load()),
                            Name(id='d', ctx=Load())],
                        keywords=[]))])],
    type_ignores=[])

Определения функций и классовFunction and class definitions

class ast.FunctionDef(name, args, body, decorator_list, returns, type_comment)

Определение функции.

  • name – это необработанная строка имени функции.

  • args – это узел arguments.

  • body – это список узлов внутри функции.

  • decorator_list – это список декораторов, которые будут применены; декораторы перечислены от самого внешнего к внутреннему (т.е. первый в списке применяется последним).

  • returns – это аннотация возвращаемого значения.

type_comment

type_comment – это необязательная строка с аннотацией типа в виде комментария.

class ast.Lambda(args, body)

lambda – это минимальное определение функции, которое можно использовать внутри выражения. В отличие от FunctionDef, body содержит один узел.

>>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4))
Module(
    body=[
        Expr(
            value=Lambda(
                args=arguments(
                    posonlyargs=[],
                    args=[
                        arg(arg='x'),
                        arg(arg='y')],
                    kwonlyargs=[],
                    kw_defaults=[],
                    defaults=[]),
                body=Constant(value=Ellipsis)))],
    type_ignores=[])
class ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)

Аргументы функции.

  • posonlyargs, args и kwonlyargs – это списки узлов arg.

  • vararg и kwarg – это одиночные узлы arg, ссылающиеся на параметры *args, **kwargs.

  • kw_defaults – это список значений по умолчанию для keyword-only аргументов. Если один из них равен None, соответствующий аргумент обязателен.

  • defaults – это список значений по умолчанию для аргументов, которые можно передавать позиционно. Если значений по умолчанию меньше, они соответствуют последним n аргументам.

class ast.arg(arg, annotation, type_comment)

Один аргумент в списке. arg – это сырая строка с именем аргумента, annotation – это его аннотация, например, узел Str или Name.

type_comment

type_comment – это необязательная строка с аннотацией типа в виде комментария

>>> print(ast.dump(ast.parse("""\
... @decorator1
... @decorator2
... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation':
...     pass
... """), indent=4))
Module(
    body=[
        FunctionDef(
            name='f',
            args=arguments(
                posonlyargs=[],
                args=[
                    arg(
                        arg='a',
                        annotation=Constant(value='annotation')),
                    arg(arg='b'),
                    arg(arg='c')],
                vararg=arg(arg='d'),
                kwonlyargs=[
                    arg(arg='e'),
                    arg(arg='f')],
                kw_defaults=[
                    None,
                    Constant(value=3)],
                kwarg=arg(arg='g'),
                defaults=[
                    Constant(value=1),
                    Constant(value=2)]),
            body=[
                Pass()],
            decorator_list=[
                Name(id='decorator1', ctx=Load()),
                Name(id='decorator2', ctx=Load())],
            returns=Constant(value='return annotation'))],
    type_ignores=[])
class ast.Return(value)

Инструкция return.

>>> print(ast.dump(ast.parse('return 4'), indent=4))
Module(
    body=[
        Return(
            value=Constant(value=4))],
    type_ignores=[])
class ast.Yield(value)
class ast.YieldFrom(value)

Выражение yield или yield from. Поскольку это выражения, их необходимо обернуть в узел Expr, если возвращаемое значение не используется.

>>> print(ast.dump(ast.parse('yield x'), indent=4))
Module(
    body=[
        Expr(
            value=Yield(
                value=Name(id='x', ctx=Load())))],
    type_ignores=[])

>>> print(ast.dump(ast.parse('yield from x'), indent=4))
Module(
    body=[
        Expr(
            value=YieldFrom(
                value=Name(id='x', ctx=Load())))],
    type_ignores=[])
class ast.Global(names)
class ast.Nonlocal(names)

Инструкции global и nonlocal. names – это список сырых строк.

>>> print(ast.dump(ast.parse('global x,y,z'), indent=4))
Module(
    body=[
        Global(
            names=[
                'x',
                'y',
                'z'])],
    type_ignores=[])

>>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4))
Module(
    body=[
        Nonlocal(
            names=[
                'x',
                'y',
                'z'])],
    type_ignores=[])
class ast.ClassDef(name, bases, keywords, starargs, kwargs, body, decorator_list)

Определение класса.

  • name – это сырая строка с именем класса.

  • bases – это список узлов для явно указанных базовых классов.

  • keywords – это список узлов keyword, в основном для «metaclass». Остальные ключевые слова будут переданы метаклассу в соответствии с PEP-3115.

  • starargs и kwargs – каждый является отдельным узлом, как при вызове функции. starargs будет развёрнут для присоединения к списку базовых классов, а kwargs будет передан метаклассу.

  • body – это список узлов, представляющих код внутри определения класса.

  • decorator_list – это список узлов, как и в FunctionDef.

>>> print(ast.dump(ast.parse("""\
... @decorator1
... @decorator2
... class Foo(base1, base2, metaclass=meta):
...     pass
... """), indent=4))
Module(
    body=[
        ClassDef(
            name='Foo',
            bases=[
                Name(id='base1', ctx=Load()),
                Name(id='base2', ctx=Load())],
            keywords=[
                keyword(
                    arg='metaclass',
                    value=Name(id='meta', ctx=Load()))],
            body=[
                Pass()],
            decorator_list=[
                Name(id='decorator1', ctx=Load()),
                Name(id='decorator2', ctx=Load())])],
    type_ignores=[])

async и awaitAsync and await

class ast.AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment)

Определение функции async def. Имеет те же поля, что и FunctionDef.

class ast.Await(value)

Выражение await. value – это то, чего оно ожидает. Допустимо только в теле AsyncFunctionDef.

>>> print(ast.dump(ast.parse("""\
... async def f():
...     await other_func()
... """), indent=4))
Module(
    body=[
        AsyncFunctionDef(
            name='f',
            args=arguments(
                posonlyargs=[],
                args=[],
                kwonlyargs=[],
                kw_defaults=[],
                defaults=[]),
            body=[
                Expr(
                    value=Await(
                        value=Call(
                            func=Name(id='other_func', ctx=Load()),
                            args=[],
                            keywords=[])))],
            decorator_list=[])],
    type_ignores=[])
class ast.AsyncFor(target, iter, body, orelse, type_comment)
class ast.AsyncWith(items, body, type_comment)

async for циклы и async with менеджеры контекста. Они имеют те же поля, что For и With, соответственно. Допустимы только в теле AsyncFunctionDef.

Примечание

Когда строка разбирается парсером ast.parse(), узлы операторов (подклассы ast.operator, ast.unaryop, ast.cmpop, ast.boolop и ast.expr_context) на возвращаемом дереве являются синглтонами. Изменения в одном будут отражены во всех других вхождениях того же значения (например, ast.Add).

ast Вспомогательные функцииast Helpers

Помимо классов узлов, модуль ast определяет следующие служебные функции и классы для обхода абстрактных синтаксических деревьев:

ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None)

Разбирает исходный код в узел AST. Эквивалентно compile(source, filename, mode, ast.PyCF_ONLY_AST).

Если задан type_comments=True, парсер изменяется, чтобы проверять и возвращать комментарии типов, как указано в PEP 484 и PEP 526. Это эквивалентно добавлению ast.PyCF_TYPE_COMMENTS к флагам, передаваемым в compile(). Это приведёт к сообщению об ошибках синтаксиса для неправильно расположенных комментариев типов. Без этого флага комментарии типов будут игнорироваться, и поле type_comment в выбранных узлах AST всегда будет None. Кроме того, расположение комментариев # type: ignore будет возвращаться как атрибут type_ignores объекта Module (иначе это всегда пустой список).

Кроме того, если mode равно 'func_type', синтаксис входных данных изменяется в соответствии с PEP 484 «сигнатурными комментариями типов», например (str, int) -> List[str].

Также установка feature_version в кортеж (major, minor) попытается выполнить разбор с использованием грамматики этой версии Python. В настоящее время major должно быть равно 3. Например, установка feature_version=(3, 4) разрешит использование async и await в качестве имён переменных. Минимальная поддерживаемая версия – (3, 4); максимальная – sys.version_info[0:2].

Если source содержит нулевой символ ('0'), возбуждается ValueError.

Предупреждение

Обратите внимание, что успешный разбор исходного кода в объект AST не гарантирует, что предоставленный исходный код является корректным кодом Python, который можно выполнить, поскольку этап компиляции может вызывать дополнительные исключения SyntaxError. Например, исходный код return 42 генерирует корректный узел AST для инструкции return, но его нельзя скомпилировать отдельно (он должен находиться внутри узла функции).

В частности, ast.parse() не выполняет никаких проверок областей видимости, которые выполняет этап компиляции.

Предупреждение

Можно вызвать сбой интерпретатора Python с помощью достаточно большой/сложной строки из-за ограничений глубины стека в компиляторе AST Python.

Изменено в версии 3.8: Добавлены type_comments, mode='func_type' и feature_version.

ast.unparse(ast_obj)

Выполняет обратный разбор объекта ast.AST и генерирует строку с кодом, который при обратном разборе с помощью ast.parse() даст эквивалентный объект ast.AST.

Предупреждение

Полученная строка кода не обязательно будет равна исходному коду, который породил объект ast.AST (без каких-либо оптимизаций компилятора, таких как константные кортежи/frozensets).

Предупреждение

Попытка выполнить обратный разбор очень сложного выражения приведёт к RecursionError.

Новое в версии 3.9.

ast.literal_eval(node_or_string)

Вычисляет узел выражения или строку, содержащую только литерал Python или отображение контейнера. Предоставленная строка или узел могут состоять только из следующих структур литералов Python: строки, байты, числа, кортежи, списки, словари, множества, булевы значения и None.

Это можно использовать для вычисления строк, содержащих значения Python, без необходимости разбирать значения самостоятельно. Он не способен вычислять произвольно сложные выражения, например, с операторами или индексацией.

Раньше эта функция документировалась как «безопасная» без определения, что это значит. Это вводило в заблуждение. Она специально разработана так, чтобы не выполнять код Python, в отличие от более общей eval(). Нет пространства имён, поиска имён или возможности внешних вызовов. Но она не свободна от атак: относительно небольшой ввод может привести к истощению памяти или истощению стека C, что вызовет сбой процесса. Также существует возможность отказа в обслуживании из-за чрезмерного потребления ЦП на некоторых входных данных. Поэтому вызывать её на недоверенных данных не рекомендуется.

Предупреждение

Можно вызвать сбой интерпретатора Python из-за ограничений глубины стека в компиляторе AST Python.

Изменено в версии 3.2: Теперь допускает литералы байтов и множеств.

Изменено в версии 3.9: Теперь поддерживает создание пустых множеств с помощью 'set()'.

ast.get_docstring(node, clean=True)

Возвращает строку документации для данного узла (который должен быть узлом FunctionDef, AsyncFunctionDef, ClassDef или Module) или None, если у него нет строки документации. Если clean истинно, очищает отступы строки документации с помощью inspect.cleandoc().

Изменено в версии 3.5: Теперь поддерживается AsyncFunctionDef.

ast.get_source_segment(source, node, *, padded=False)

Возвращает фрагмент исходного кода из source, который породил узел node. Если не хватает информации о местоположении (lineno, end_lineno, col_offset или end_col_offset), возвращает None.

Если padded равно True, первая строка многострочного оператора будет дополнена пробелами, чтобы соответствовать исходной позиции.

Новое в версии 3.8.

ast.fix_missing_locations(node)

При компиляции дерева узлов с помощью compile() компилятор ожидает атрибуты lineno и col_offset для каждого узла, который их поддерживает. Заполнять их вручную для сгенерированных узлов довольно утомительно, поэтому эта вспомогательная функция рекурсивно добавляет эти атрибуты, если их ещё нет, устанавливая их равными значениям родительского узла. Работает рекурсивно, начиная с node.

ast.increment_lineno(node, n=1)

Увеличивает номер строки и номер конечной строки каждого узла в дереве, начиная с node, на n. Это полезно для «перемещения кода» в другое место в файле.

ast.copy_location(new_node, old_node)

Копирует информацию о местоположении в исходном коде (lineno, col_offset, end_lineno и end_col_offset) из old_node в new_node, если это возможно, и возвращает new_node.

ast.iter_fields(node)

Генерирует кортеж из (fieldname, value) для каждого поля в node._fields, которое присутствует в node.

ast.iter_child_nodes(node)

Генерирует все непосредственные дочерние узлы node, то есть все поля, являющиеся узлами, и все элементы полей, являющихся списками узлов.

ast.walk(node)

Рекурсивно генерирует все узлы-потомки в дереве, начиная с node (включая сам node), в произвольном порядке. Это полезно, если требуется только изменить узлы на месте, а контекст не важен.

class ast.NodeVisitor

Базовый класс для обхода узлов, который обходит абстрактное синтаксическое дерево и вызывает функцию-посетитель для каждого найденного узла. Эта функция может вернуть значение, которое передаётся методом visit().

Этот класс предназначен для наследования; в подклассе добавляются методы-посетители.

visit(node)

Посещает узел. Реализация по умолчанию вызывает метод self.visit_classname, где classname – имя класса узла, или generic_visit(), если такой метод отсутствует.

generic_visit(node)

Этот посетитель вызывает visit() для всех дочерних узлов.

Обратите внимание, что дочерние узлы тех узлов, для которых определён собственный метод-посетитель, не будут посещены, если посетитель сам не вызовет generic_visit() или не обойдёт их самостоятельно.

Не используйте NodeVisitor, если требуется вносить изменения в узлы во время обхода. Для этого существует специальный посетитель (NodeTransformer), который допускает модификации.

Устарело с версии 3.8: Методы visit_Num(), visit_Str(), visit_Bytes(), visit_NameConstant() и visit_Ellipsis() теперь устарели и не будут вызываться в будущих версиях Python. Добавьте метод visit_Constant() для обработки всех узлов-констант.

class ast.NodeTransformer

Подкласс NodeVisitor, который обходит абстрактное синтаксическое дерево и позволяет изменять узлы.

Метод NodeTransformer обходит AST и использует возвращаемое значение методов-посетителей для замены или удаления старого узла. Если возвращаемое значение метода-посетителя равно None, узел будет удалён из своего местоположения; в противном случае он заменяется возвращённым значением. Возвращённое значение может быть исходным узлом – в этом случае замена не происходит.

Вот пример преобразователя, который переписывает все обращения к именам (foo) в data['foo']:

class RewriteName(NodeTransformer):

    def visit_Name(self, node):
        return Subscript(
            value=Name(id='data', ctx=Load()),
            slice=Constant(value=node.id),
            ctx=node.ctx
        )

Имейте в виду: если у узла, с которым вы работаете, есть дочерние узлы, необходимо либо преобразовать дочерние узлы самостоятельно, либо сначала вызвать для узла метод generic_visit().

Для узлов, входящих в состав набора инструкций (это относится ко всем узлам инструкций), посетитель может также возвращать список узлов, а не один узел.

Если NodeTransformer вводит новые узлы (не входившие в исходное дерево) без указания информации о расположении (например, lineno), следует вызвать fix_missing_locations() для нового поддерева, чтобы пересчитать информацию о расположении:

tree = ast.parse('foo', mode='eval')
new_tree = fix_missing_locations(RewriteName().visit(tree))

Обычно преобразователь используется следующим образом:

node = YourTransformer().visit(node)
ast.dump(node, annotate_fields=True, include_attributes=False, *, indent=None)

Возвращает форматированный дамп дерева из node. Это в основном полезно для отладки. Если annotate_fields равно true (по умолчанию), возвращаемая строка будет показывать имена и значения полей. Если annotate_fields равно false, результирующая строка будет более компактной за счёт опускания однозначных имён полей. Атрибуты, такие как номера строк и смещения столбцов, по умолчанию не выводятся. Если это нужно, include_attributes можно установить в true.

Если indent – неотрицательное целое число или строка, дерево будет выведено с отступами указанного уровня. Уровень отступа 0, отрицательное значение или "" вставляет только переводы строк. None (по умолчанию) выбирает однострочное представление. Положительный целочисленный отступ добавляет соответствующее количество пробелов на уровень. Если indent – строка (например, "\t"), эта строка используется для отступа каждого уровня.

Изменено в версии 3.9: Добавлена опция indent.

Флаги компилятораCompiler Flags

Следующие флаги могут быть переданы в compile() для изменения эффектов компиляции программы:

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

Включает поддержку await, async for, async with и асинхронных включений верхнего уровня.

Новое в версии 3.8.

ast.PyCF_ONLY_AST

Генерирует и возвращает абстрактное синтаксическое дерево вместо скомпилированного объекта кода.

ast.PyCF_TYPE_COMMENTS

Включает поддержку комментариев типов в стиле PEP 484 и PEP 526 (# type: <type>, # type: ignore <stuff>).

Новое в версии 3.8.

Использование командной строкиCommand-Line Usage

Новое в версии 3.9.

Модуль ast может быть выполнен как скрипт из командной строки. Это просто:

python -m ast [-m <mode>] [-a] [infile]

Принимаются следующие опции:

-h, --help

Показать справку и выйти.

-m <mode>
--mode <mode>

Определяет, какой вид кода должен быть скомпилирован, как аргумент mode в parse().

--no-type-comments

Не обрабатывать комментарии типов.

-a, --include-attributes

Включать атрибуты, такие как номера строк и смещения столбцов.

-i <indent>
--indent <indent>

Отступ узлов в AST (количество пробелов).

Если указан infile, его содержимое разбирается в AST и выводится в stdout. В противном случае содержимое читается из stdin.

См. также

Green Tree Snakes – внешний документационный ресурс, содержащий подробности работы с AST Python.

ASTTokens дополняет AST Python позициями токенов и текста в исходном коде, который их породил. Это полезно для инструментов, выполняющих преобразования исходного кода.

leoAst.py объединяет представления программ на Python на основе токенов и синтаксических деревьев, вставляя двусторонние связи между токенами и узлами AST.

LibCST разбирает код как конкретное синтаксическое дерево, похожее на AST, и сохраняет все детали форматирования. Это полезно для создания приложений автоматического рефакторинга (codemod) и линтеров.

Parso – это синтаксический анализатор Python, поддерживающий восстановление после ошибок и сквозной разбор для разных версий Python (на нескольких версиях Python). Parso также может перечислять несколько синтаксических ошибок в файле Python.