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, который воспроизведён выше. Они определены в модуле 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 и материалов его участников.

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

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, а также неизменяемыми контейнерами (кортежами и frozenset), если все их элементы являются константами.

>>> 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
    • 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, а на соответствующей позиции в keys указывается None.

>>> 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 создаётся оператором присваивания-выражения (также известным как оператор-морж). В отличие от узла 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. 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 содержит список узлов для выполнения, если образец соответствует объекту, а результат вычисления выражения-ограничения истинен.

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

Образец с конструкцией «as», образец захвата или образец-шаблон. 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 — список значений по умолчанию для аргументов, доступных только по имени. Если значение равно None, соответствующий аргумент является обязательным.
  • 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.

Асинхронные операции и await

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

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

Из-за ограничений глубины стека в компиляторе AST Python интерпретатор 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, без необходимости самостоятельно разбирать эти значения. Она не предназначена для вычисления произвольных сложных выражений, например выражений с операторами или индексацией.

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

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

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

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

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

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

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

ast.get_docstring(node, clean=True)

Возвращает строку документации заданного узла (который должен быть узлом 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. Это полезно, чтобы «переместить код» в другое место файла.

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)

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

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 — строка (например, "\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.

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

Добавлено в версии 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.

© 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