Spec-Zone.ru › Python 3.12

ast — Абстрактные синтаксические деревья

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

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

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

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

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

-- ASDL's 4 builtin types are:
-- identifier, int, string, constant

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, type_param* type_params)
          | AsyncFunctionDef(identifier name, arguments args,
                             stmt* body, expr* decorator_list, expr? returns,
                             string? type_comment, type_param* type_params)

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

          | Delete(expr* targets)
          | Assign(expr* targets, expr value, string? type_comment)
          | TypeAlias(expr name, type_param* type_params, expr value)
          | AugAssign(expr target, operator op, expr value)
          -- 'simple' indicates that we annotate simple name without parens
          | AnnAssign(expr target, expr annotation, expr? value, int simple)

          -- use 'orelse' because else is a keyword in target languages
          | 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)

          | Match(expr subject, match_case* cases)

          | Raise(expr? exc, expr? cause)
          | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
          | TryStar(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 is the byte offset in the utf8 string the parser uses
          attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

          -- BoolOp() can use 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)
         -- the grammar constrains where yield expressions can occur
         | Await(expr value)
         | Yield(expr? value)
         | YieldFrom(expr value)
         -- need sequences for compare to distinguish between
         -- 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)

         -- the following expression can appear in assignment context
         | 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)

         -- can appear only in Subscript
         | Slice(expr? lower, expr? upper, expr? step)

          -- col_offset is the byte offset in the utf8 string the parser uses
          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)

    -- keyword arguments supplied to call (NULL identifier for **kwargs)
    keyword = (identifier? arg, expr value)
               attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    -- import name with optional 'as' alias.
    alias = (identifier name, identifier? asname)
             attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    withitem = (expr context_expr, expr? optional_vars)

    match_case = (pattern pattern, expr? guard, stmt* body)

    pattern = MatchValue(expr value)
            | MatchSingleton(constant value)
            | MatchSequence(pattern* patterns)
            | MatchMapping(expr* keys, pattern* patterns, identifier? rest)
            | MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)

            | MatchStar(identifier? name)
            -- The optional "rest" MatchMapping parameter handles capturing extra mapping keys

            | MatchAs(pattern? pattern, identifier? name)
            | MatchOr(pattern* patterns)

             attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)

    type_ignore = TypeIgnore(int lineno, string tag)

    type_param = TypeVar(identifier name, expr? bound)
               | ParamSpec(identifier name)
               | TypeVarTuple(identifier name)
               attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
}

Классы узлов

class ast.AST

Это базовый класс для всех классов узлов AST. Фактические классы узлов наследуются от файла Parser/Python.asdl, который воспроизведён выше. Они определены в модуле _ast C и повторно экспортированы в 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 и всех его участников.

Корневые узлы

class ast.Module(body, type_ignores)

Модуль Python, как и в случае с вводом из файла. Тип узла, генерируемый ast.parse() в режиме "exec".

body — список list утверждений модуля.

type_ignores — список list комментариев модуля о игнорировании типов; см. ast.parse() для получения дополнительной информации.

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

Одно выражение Python ввода выражения. Тип узла, генерируемый ast.parse(), когда mode равен "eval".

body — единственный узел, один из типов выражений.

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

Один ввод в интерактивном режиме, как в Режим интерактивного режима. Тип узла, генерируемый ast.parse(), когда mode равен "single".

body — список list узлов операторов.

>>> print(ast.dump(ast.parse('x = 1; y = 2', mode='single'), indent=4))
Interactive(
    body=[
        Assign(
            targets=[
                Name(id='x', ctx=Store())],
            value=Constant(value=1)),
        Assign(
            targets=[
                Name(id='y', ctx=Store())],
            value=Constant(value=2))])
class ast.FunctionType(argtypes, returns)

Представление комментариев старого стиля для функций, так как версии Python до 3.5 не поддерживали PEP 484 аннотации. Тип узла, генерируемый ast.parse(), когда mode равен "func_type".

Комментарии такого типа выглядели бы так:

def sum_two_number(a, b):
    # type: (int, int) -> int
    return a + b

argtypes — список list узлов выражений.

returns — единственный узел выражения.

>>> print(ast.dump(ast.parse('(int, str) -> List[int]', mode='func_type'), indent=4))
FunctionType(
    argtypes=[
        Name(id='int', ctx=Load()),
        Name(id='str', ctx=Load())],
    returns=Subscript(
        value=Name(id='List', ctx=Load()),
        slice=Name(id='int', ctx=Load()),
        ctx=Load()))

Добавлен в версии 3.8.

Литералы

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: форматирование repr !r
    • 97: форматирование ascii !a
  • 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())]))

Переменные

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=[])

Выражения

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)

Булева операция, «или» или «и». 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)

Вызов функции. func — функция, которая часто будет объектом Name или Attribute. Из аргументов:

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

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

>>> 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 — это строка, содержащая имя атрибута, а ctx — Load, 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 создаётся оператором присваивания выражений (также известным как оператор walrus). В отличие от узла 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)))

Добавлен в версии 3.8.

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

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()))

Сжатия

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)) # Multiple comprehensions in one.
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)) # generator comprehension
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)) # Async comprehension
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)]))

Утверждения

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)) # Multiple assignment
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)) # Unpacking
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 всегда равен либо 0 (указывая на «сложный» целевой объект), либо 1 (указывая на «простой» целевой объект). «Простой» целевой объект состоит только из узла Name, который не находится в скобках; все остальные целевые объекты считаются сложными. Только простые целевые объекты появляются в словаре __annotations__ модулей и классов.

>>> 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)) # Annotation with parenthesis
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)) # Attribute annotation
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)) # Subscript annotation
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 — это узел Name для x (с контекстом Store), op — это Add, а value — это Constant со значением 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 — это объект исключения, который необходимо поднять, обычно Call или Name, или None для самостоятельного raise. cause — это необязательная часть для y в raise x from 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=[])
class ast.TypeAlias(name, type_params, value)

Псевдоним типа type alias, созданный с помощью оператора type. name — это имя псевдонима, type_params — это список параметров типа, а value — это значение псевдонима типа.

>>> print(ast.dump(ast.parse('type Alias = int'), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[],
            value=Name(id='int', ctx=Load()))],
    type_ignores=[])

Добавлен в версии 3.12.

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

Импорты

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=[])

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

Примечание

Необязательные фрагменты, такие как 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, Attribute или Subscript. 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.TryStar(body, handlers, orelse, finalbody)

Блоки try, за которыми следуют фрагменты except*. Атрибуты такие же, как у Try, но узлы ExceptHandler в handlers интерпретируются как блоки except*, а не except.

>>> print(ast.dump(ast.parse("""
... try:
...    ...
... except* Exception:
...    ...
... """), indent=4))
Module(
    body=[
        TryStar(
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            handlers=[
                ExceptHandler(
                    type=Name(id='Exception', ctx=Load()),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])],
            orelse=[],
            finalbody=[])],
    type_ignores=[])

Добавлен в версии 3.11.

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=[])

Сопоставление с образцом

class ast.Match(subject, cases)

Оператор match. subject содержит предмет сопоставления (объект, который сопоставляется с вариантами), а cases содержит итерируемый список узлов match_case с различными вариантами.

Добавлен в версии 3.10.

class ast.match_case(pattern, guard, body)

Один вариант шаблона в операторе match. pattern содержит шаблон сопоставления, с которым будет сопоставляться предмет. Обратите внимание, что узлы AST, генерируемые для шаблонов, отличаются от узлов, генерируемых для выражений, даже если у них одинаковый синтаксис.

Атрибут guard содержит выражение, которое будет вычислено, если шаблон соответствует предмету.

body содержит список узлов, которые будут выполнены, если шаблон соответствует и результат вычисления выражения условия равен true.

>>> print(ast.dump(ast.parse("""
... match x:
...     case [x] if x>0:
...         ...
...     case tuple():
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchAs(name='x')]),
                    guard=Compare(
                        left=Name(id='x', ctx=Load()),
                        ops=[
                            Gt()],
                        comparators=[
                            Constant(value=0)]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='tuple', ctx=Load()),
                        patterns=[],
                        kwd_attrs=[],
                        kwd_patterns=[]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

Добавлен в версии 3.10.

class ast.MatchValue(value)

Шаблон соответствия литералу или значению, сравнивающий по равенству. value — это узел выражения. Разрешенные узлы значений ограничены, как описано в документации к оператору сопоставления. Этот шаблон срабатывает, если предмет сопоставления равен вычисленному значению.

>>> print(ast.dump(ast.parse("""
... match x:
...     case "Relevant":
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchValue(
                        value=Constant(value='Relevant')),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

Добавлен в версии 3.10.

class ast.MatchSingleton(value)

Шаблон соответствия литералу, сравнивающий по идентичности. value — это единственный объект для сравнения: None, True, или False. Этот шаблон срабатывает, если предмет сопоставления является заданной константой.

>>> print(ast.dump(ast.parse("""
... match x:
...     case None:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchSingleton(value=None),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

Добавлен в версии 3.10.

class ast.MatchSequence(patterns)

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

>>> print(ast.dump(ast.parse("""
... match x:
...     case [1, 2]:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchValue(
                                value=Constant(value=1)),
                            MatchValue(
                                value=Constant(value=2))]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

Добавлен в версии 3.10.

class ast.MatchStar(name)

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

>>> print(ast.dump(ast.parse("""
... match x:
...     case [1, 2, *rest]:
...         ...
...     case [*_]:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchValue(
                                value=Constant(value=1)),
                            MatchValue(
                                value=Constant(value=2)),
                            MatchStar(name='rest')]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchStar()]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

Добавлен в версии 3.10.

class ast.MatchMapping(keys, patterns, rest)

Шаблон соответствия отображению. keys — это последовательность узлов выражений. patterns — это соответствующая последовательность узлов шаблонов. rest — это необязательное имя, которое можно указать для захвата оставшихся элементов отображения. Разрешенные выражения ключей ограничены, как описано в документации к оператору сопоставления.

Этот шаблон срабатывает, если предмет является отображением, все вычисленные выражения ключей присутствуют в отображении, и значение, соответствующее каждому ключу, соответствует соответствующему подшаблону. Если rest не None, словарь, содержащий оставшиеся элементы отображения, привязывается к этому имени, если шаблон всего отображения успешен.

>>> print(ast.dump(ast.parse("""
... match x:
...     case {1: _, 2: _}:
...         ...
...     case {**rest}:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchMapping(
                        keys=[
                            Constant(value=1),
                            Constant(value=2)],
                        patterns=[
                            MatchAs(),
                            MatchAs()]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchMapping(keys=[], patterns=[], rest='rest'),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

Добавлен в версии 3.10.

class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)

Шаблон соответствия классу. cls — это выражение, указывающее номинальный класс, который нужно сопоставить. patterns — это последовательность узлов шаблонов, которые нужно сопоставить с определённой последовательностью атрибутов класса. kwd_attrs — это последовательность дополнительных атрибутов, которые нужно сопоставить (указанных как ключевые аргументы в шаблоне класса), kwd_patterns — соответствующие шаблоны (указанные как ключевые значения в шаблоне класса).

Этот шаблон срабатывает, если предмет является экземпляром указанного класса, все позиционные шаблоны соответствуют соответствующим атрибутам класса и все указанные ключевые атрибуты соответствуют их соответствующим шаблонам.

Примечание: классы могут определять свойство, которое возвращает self, чтобы сопоставить узел шаблона с экземпляром, который сопоставляется. Также несколько встроенных типов сопоставляются таким образом, как описано в документации к оператору сопоставления.

>>> print(ast.dump(ast.parse("""
... match x:
...     case Point2D(0, 0):
...         ...
...     case Point3D(x=0, y=0, z=0):
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='Point2D', ctx=Load()),
                        patterns=[
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0))],
                        kwd_attrs=[],
                        kwd_patterns=[]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='Point3D', ctx=Load()),
                        patterns=[],
                        kwd_attrs=[
                            'x',
                            'y',
                            'z'],
                        kwd_patterns=[
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0))]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

Добавлен в версии 3.10.

class ast.MatchAs(pattern, name)

Шаблон «как», шаблон захвата или шаблон подстановки. pattern содержит шаблон соответствия, с которым будет сопоставляться предмет. Если шаблон None, узел представляет шаблон захвата (т.е. простое имя) и всегда будет успешным.

Атрибут name содержит имя, которое будет привязано, если шаблон успешен. Если name — это None, pattern также должен быть None, и узел представляет шаблон подстановки.

>>> print(ast.dump(ast.parse("""
... match x:
...     case [x] as y:
...         ...
...     case _:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchAs(
                        pattern=MatchSequence(
                            patterns=[
                                MatchAs(name='x')]),
                        name='y'),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchAs(),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

Добавлен в версии 3.10.

class ast.MatchOr(patterns)

Шаблон «или». Шаблон «или» последовательно сопоставляет каждый из своих подшаблонов с предметом, пока один из них не совпадёт. Шаблон «или» считается успешным. Если ни один из подшаблонов не совпадёт, шаблон «или» считается неуспешным. Атрибут patterns содержит список узлов шаблонов, которые будут сопоставлены с предметом.

>>> print(ast.dump(ast.parse("""
... match x:
...     case [x] | (y):
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchOr(
                        patterns=[
                            MatchSequence(
                                patterns=[
                                    MatchAs(name='x')]),
                            MatchAs(name='y')]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

Добавлен в версии 3.10.

Параметры типов

Параметры типов могут существовать в классах, функциях и псевдонимах типов.

class ast.TypeVar(name, bound)

Переменная типа typing.TypeVar. name — имя переменной типа. bound — ограничение, если таковое имеется. Если bound — это Tuple, это ограничение; в противном случае это ограничение.

>>> print(ast.dump(ast.parse("type Alias[T: int] = list[T]"), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[
                TypeVar(
                    name='T',
                    bound=Name(id='int', ctx=Load()))],
            value=Subscript(
                value=Name(id='list', ctx=Load()),
                slice=Name(id='T', ctx=Load()),
                ctx=Load()))],
    type_ignores=[])

Добавлен в версии 3.12.

class ast.ParamSpec(name)

Спецификация параметра typing.ParamSpec. name — имя спецификации параметра.

>>> print(ast.dump(ast.parse("type Alias[**P] = Callable[P, int]"), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[
                ParamSpec(name='P')],
            value=Subscript(
                value=Name(id='Callable', ctx=Load()),
                slice=Tuple(
                    elts=[
                        Name(id='P', ctx=Load()),
                        Name(id='int', ctx=Load())],
                    ctx=Load()),
                ctx=Load()))],
    type_ignores=[])

Добавлен в версии 3.12.

class ast.TypeVarTuple(name)

Кортеж переменных типа typing.TypeVarTuple. name — имя кортежа переменных типа.

>>> print(ast.dump(ast.parse("type Alias[*Ts] = tuple[*Ts]"), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[
                TypeVarTuple(name='Ts')],
            value=Subscript(
                value=Name(id='tuple', ctx=Load()),
                slice=Tuple(
                    elts=[
                        Starred(
                            value=Name(id='Ts', ctx=Load()),
                            ctx=Load())],
                    ctx=Load()),
                ctx=Load()))],
    type_ignores=[])

Добавлен в версии 3.12.

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

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

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

  • name — это строка с именем функции.
  • args — это узел arguments.
  • body — это список узлов внутри функции.
  • decorator_list — это список декораторов, которые будут применяться, от внешнего к внутреннему (т.е. первый в списке будет применён последним).
  • returns — это аннотация возвращаемого значения.
  • type_params — это список параметров типа.
type_comment

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

Изменено в версии 3.12: Добавлен type_params.

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 — это список значений по умолчанию для ключевых аргументов. Если значение отсутствует, соответствующий аргумент обязателен.
  • defaults — это список значений по умолчанию для позиционных аргументов. Если значений меньше, они соответствуют последним n аргументам.
class ast.arg(arg, annotation, type_comment)

Один аргумент в списке. arg — это строка с именем аргумента; annotation — его аннотация, например, узел 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_params=[])],
    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, body, decorator_list, type_params)

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

  • name — это строка с именем класса
  • bases — это список узлов для явно указанных базовых классов.
  • keywords — это список узлов keyword, в основном для 'метакласса'. Другие ключевые слова будут переданы метаклассу в соответствии с PEP-3115.
  • body — это список узлов, представляющих код внутри определения класса.
  • decorator_list — это список узлов, как в FunctionDef.
  • type_params — это список параметров типа.
>>> 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_params=[])],
    type_ignores=[])

Изменено в версии 3.12: Добавлен type_params.

Асинхронные и ожидающие операции

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

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

Изменено в версии 3.12: Добавлен type_params.

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_params=[])],
    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 определяет следующие вспомогательные функции и классы для обхода абстрактных синтаксических деревьев:

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. Например, установка feature_version=(3, 9) попытается запретить парсинг инструкций match. В настоящее время major должно быть равно 3. Наименьшая поддерживаемая версия — (3, 4) (и она может увеличиться в будущих версиях Python); наибольшая — sys.version_info[0:2]. «Лучшая попытка» означает, что нет гарантии, что результат парсинга (или успех парсинга) совпадёт с результатом при выполнении на версии Python, соответствующей feature_version.

Если исходный код содержит нулевой символ (\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 (без каких-либо оптимизаций компилятора, таких как константные кортежи/замороженные множества).

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

Попытка разобрать очень сложное выражение может привести к RecursionError.

Добавлен в версии 3.9.

ast.literal_eval(node_or_string)

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

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

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

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

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

Она может генерировать исключения ValueError, TypeError, SyntaxError, MemoryError и RecursionError в зависимости от некорректного ввода.

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

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

Изменено в версии 3.10: Для строковых входных данных ведущие пробелы и табуляции теперь удаляются.

ast.get_docstring(node, clean=True)

Возвращает строку документации данного узла node (который должен быть узлом FunctionDef, AsyncFunctionDef, ClassDef или Module), или None если строка документации отсутствует. Если clean равно true, очищает отступы в строке документации с помощью 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. Это полезно для «перемещения кода» в другое место в файле.

END_OF_DOCUMENT_MARKER
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() или не посетит их самостоятельно.

visit_Constant(node)

Обрабатывает все постоянные узлы.

Не используйте 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 отступает на столько пробелов на каждый уровень. Если indent — строка (например, "\t"), эта строка используется для отступа каждого уровня.

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

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

Следующие флаги можно передать в 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.

END_OF_DOCUMENT_MARKER

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

Добавлен в версии 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 и выведено в стандартный вывод. В противном случае содержимое будет считано со стандартного ввода.

См. также

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

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

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

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

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

© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/ast.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API