Spec-Zone.ru › Python 3.13

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, expr? default_value)
               | ParamSpec(identifier name, expr? default_value)
               | TypeVarTuple(identifier name, expr? default_value)
               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().

_field_types

Атрибут _field_types каждого конкретного класса представляет собой словарь, сопоставляющий имена полей (также перечисленные в _fields) с их типами.

>>> ast.TypeVar._field_types
{'name': <class 'str'>, 'bound': ast.expr | None, 'default_value': ast.expr | None}

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

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(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
                   lineno=0, col_offset=0)

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

Изменено в версии 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. Тем временем, создание их экземпляров вернёт экземпляр другого класса.

Устарело начиная с версии 3.13, будет удалено в версии 3.15: Предыдущие версии Python разрешали создание узлов AST, которым не хватало необходимых полей. Аналогично, конструкторы узлов AST допускали произвольные именованные аргументы, которые устанавливались в качестве атрибутов узла AST, даже если они не совпадали ни с одним из полей узла AST. Это поведение устарело и будет удалено в Python 3.15.

Примечание

Описание конкретных классов узлов, показанных здесь, изначально было адаптировано из замечательного проекта 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))])
class ast.Expression(body)

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

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

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

Один интерактивный ввод, как в Интерактивном режиме. Тип узла генерируется функцией ast.parse(), когда режим равен "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() когда режим равен "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: !r форматирование repr
    • 97: !a форматирование ascii
  • format_spec — это узел JoinedStr, представляющий форматирование значения, или None , если форматирование не было указано. Оба conversion и format_spec могут быть установлены одновременно.
class ast.JoinedStr(values)

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

>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4))
Expression(
    body=JoinedStr(
        values=[
            Constant(value='sin('),
            FormattedValue(
                value=Name(id='a', ctx=Load()),
                conversion=-1),
            Constant(value=') is '),
            FormattedValue(
                value=Call(
                    func=Name(id='sin', ctx=Load()),
                    args=[
                        Name(id='a', ctx=Load())]),
                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()))])

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

>>> print(ast.dump(ast.parse('del a'), indent=4))
Module(
    body=[
        Delete(
            targets=[
                Name(id='a', ctx=Del())])])
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()))])

Выражения

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())))])
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, представляющих аргументы, переданные по имени.

Аргументы 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()),
                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()),
                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()),
                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())]),
        generators=[
            comprehension(
                target=Name(id='line', ctx=Store()),
                iter=Name(id='file', ctx=Load()),
                is_async=0),
            comprehension(
                target=Name(id='c', ctx=Store()),
                iter=Name(id='line', ctx=Load()),
                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()),
                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))])

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

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

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

>>> 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)])
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))])
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()))])
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()))])
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())])])
class ast.Pass

Оператор pass.

>>> print(ast.dump(ast.parse('pass'), indent=4))
Module(
    body=[
        Pass()])
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()),
            value=Name(id='int', ctx=Load()))])

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

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

Примечание

Необязательные фрагменты кода, такие как 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))])])])
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))])])
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))])])
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()])])])
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))])])
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))])])])

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

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

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())),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])])

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

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

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

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

Добавлена в версии 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(rest='rest'),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])])

Добавлена в версии 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))]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='Point3D', ctx=Load()),
                        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))])])])

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

class ast.MatchAs(pattern, name)

Шаблон «as-pattern», шаблон захвата или шаблон подстановочного знака. 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))])])])

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

class ast.MatchOr(patterns)

Шаблон «or-pattern». Шаблон «or-pattern» по очереди сопоставляет каждый из его подшаблонов с объектом до тех пор, пока один из них не выполнится. В таком случае «or-pattern» считается выполненным. Если ни один из подшаблонов не выполнится, шаблон «or-pattern» не выполняется. Атрибут 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))])])])

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

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

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

class ast.TypeVar(name, bound, default_value)

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

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

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

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

class ast.ParamSpec(name, default_value)

Спецификация параметра typing.ParamSpec. name — имя спецификации параметра. default_value — значение по умолчанию; если у ParamSpec нет значения по умолчанию, этот атрибут будет установлен в None.

>>> print(ast.dump(ast.parse("type Alias[**P = (int, str)] = Callable[P, int]"), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[
                ParamSpec(
                    name='P',
                    default_value=Tuple(
                        elts=[
                            Name(id='int', ctx=Load()),
                            Name(id='str', ctx=Load())],
                        ctx=Load()))],
            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()))])

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

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

class ast.TypeVarTuple(name, default_value)

Кортеж переменных типа typing.TypeVarTuple. name — имя кортежа переменных типа. default_value — значение по умолчанию; если у TypeVarTuple нет значения по умолчанию, этот атрибут будет установлен в None.

>>> 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',
                    default_value=Tuple(ctx=Load()))],
            value=Subscript(
                value=Name(id='tuple', ctx=Load()),
                slice=Tuple(
                    elts=[
                        Starred(
                            value=Name(id='Ts', ctx=Load()),
                            ctx=Load())],
                    ctx=Load()),
                ctx=Load()))])

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

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

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

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(
                    args=[
                        arg(arg='x'),
                        arg(arg='y')]),
                body=Constant(value=Ellipsis)))])
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(
                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'))])
class ast.Return(value)

Оператор return.

>>> print(ast.dump(ast.parse('return 4'), indent=4))
Module(
    body=[
        Return(
            value=Constant(value=4))])
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())))])

>>> print(ast.dump(ast.parse('yield from x'), indent=4))
Module(
    body=[
        Expr(
            value=YieldFrom(
                value=Name(id='x', ctx=Load())))])
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'])])

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

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

  • name — строковое представление имени класса
  • bases — список узлов для явно указанных базовых классов.
  • keywords — список узлов keyword, в основном для ‘metaclass’. Другие ключевые слова будут переданы metaclass, в соответствии с 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())])])

Изменено в версии 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(),
            body=[
                Expr(
                    value=Await(
                        value=Call(
                            func=Name(id='other_func', ctx=Load()))))])])
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, optimize=-1)

Разбор исходного кода в узел AST. Эквивалентно compile(source, filename, mode, flags=FLAGS_VALUE, optimize=optimize), где FLAGS_VALUE равно ast.PyCF_ONLY_AST если optimize <= 0 и ast.PyCF_OPTIMIZED_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, 7) (и она может увеличиться в будущих версиях 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.

Изменено в версии 3.13: Минимально поддерживаемая версия для feature_version теперь (3, 7). Аргумент optimize был добавлен.

ast.unparse(ast_obj)

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

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

Сгенерированная строка кода не обязательно будет равна исходному коду, который сгенерировал объект 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, show_empty=False)

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

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

Если show_empty — False (по умолчанию), пустые списки и поля, которые None будут опущены из вывода.

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

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

>>> print(ast.dump(ast.parse("""\
... async def f():
...     await other_func()
... """), indent=4, show_empty=True))
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=[])

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

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

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

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

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

ast.PyCF_ONLY_AST

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

ast.PyCF_OPTIMIZED_AST

Возвращённое AST оптимизируется в соответствии с аргументом optimize в compile() или ast.parse().

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

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

См. также

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

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.13/library/ast.html

Spec-Zone.ru

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