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

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


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

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

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

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

Классы узлов

class ast.AST

Это основа всех классов узлов AST. Сами классы узлов получены из файла Parser/Python.asdl, который воспроизводится above. Они определены в модуле _ast C и повторно экспортированы в ast.

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

_fields

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

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

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

lineno
col_offset
end_lineno
end_col_offset

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

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

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

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

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

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

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

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

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

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

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

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

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

Примечание

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

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

class ast.Module(body, type_ignores)

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

тело - это 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 expression input. Тип узла генерируется с помощью ast.parse(), когда mode равен "eval".

body - это отдельный узел, один из expression types.

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

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

body - это list из statement nodes.

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

Представление типа comments старого образца для функций, поскольку версии 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 из expression nodes.

возвращает одинарный expression node.

>>> 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 повторное форматирование

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

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

class ast.JoinedStr(values)

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

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

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

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

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

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

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

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

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

Переменные

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 содержит один из других узлов в этом разделе, a Constant, a 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 - это узел, обычно a 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)))

Индексация

class ast.Subscript(value, slice, ctx)

Индекс, такой как l[1]. value, - это объект, на который делается подписка (обычно это последовательность или отображение). slice - это индекс, фрагмент или ключ. Это может быть Tuple и содержать Slice. ctx is 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 - это объект для итерации over. 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 - логическое целое число, которому присвоено значение True для Name узла в target, которые не они заключены в круглые скобки и, следовательно, являются нашими именами, а не выражениями.

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

>>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # 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.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 предложения не имеют специального представления в PAST, а скорее отображаются как дополнительные узлы If в разделе orelse предыдущего раздела.

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

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

type_comment

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

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

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

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

Операторы break и continue.

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

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

>>> print(ast.dump(ast.parse("""
... try:
...    ...
... except Exception:
...    ...
... except OtherException as e:
...    ...
... else:
...    ...
... finally:
...    ...
... """), indent=4))
Module(
    body=[
        Try(
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            handlers=[
                ExceptHandler(
                    type=Name(id='Exception', ctx=Load()),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                ExceptHandler(
                    type=Name(id='OtherException', ctx=Load()),
                    name='e',
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])],
            orelse=[
                Expr(
                    value=Constant(value=Ellipsis))],
            finalbody=[
                Expr(
                    value=Constant(value=Ellipsis))])],
    type_ignores=[])
class ast.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=[])
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 узлов с различными регистрами.

class ast.match_case(pattern, guard, body)

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

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

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

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

Соответствующий литерал или шаблон значений, который сравнивается по равенству. value является узлом выражения. Допустимые узлы значений ограничены, как описано в документации к инструкции match. Этот шаблон выполняется успешно, если объект соответствия равен вычисленному значению.

>>> 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=[])
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=[])
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=[])
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=[])
class ast.MatchMapping(keys, patterns, rest)

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

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

>>> 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=[])
class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)

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

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

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

>>> 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=[])
class ast.MatchAs(pattern, name)

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

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

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

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

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

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

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

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

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

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

  • decorator_list - это список применяемых декораторов, который хранится самым первым (т.е. первый в списке будет применен последним).

  • returns - это аннотация к возврату.

type_comment

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

class ast.Lambda(args, body)

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

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

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

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

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

  • kw_defaults - это список значений по умолчанию для аргументов, содержащих только ключевые слова. Если значение равно 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_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)

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

  • name - это необработанная строка для имени класса

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

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

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

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

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

Асинхронность и ожидание

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

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

class ast.Await(value)

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

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

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

Примечание

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

ast Помощники

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

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.

Если исходный код содержит символ null, то возникает значение (\0), ValueError.

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

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

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

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

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

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

ast.unparse(ast_obj)

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

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

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

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

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

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

ast.literal_eval(node_or_string)

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

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

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

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

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

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

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

Изменено в версии 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)

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

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

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

ast.fix_missing_locations(node)

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

ast.increment_lineno(node, n=1)

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

ast.copy_location(new_node, old_node)

Скопируйте исходное местоположение (lineno, col_offset, end_lineno, и end_col_offset) из old_node в new_node, если это возможно, и верните new_node.

ast.iter_fields(node)

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

ast.iter_child_nodes(node)

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

ast.walk(node)

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

class ast.NodeVisitor

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

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

visit(node)

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

generic_visit(node)

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

Обратите внимание, что дочерние узлы узлов, у которых есть пользовательский метод visitor, не будут посещены, если посетитель не вызовет 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 и использовать возвращаемое значение методов visitor для замены или удаления старого узла. Если возвращаемое значение метода visitor равно 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: Добавлена опция отступ.

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

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

См.также

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

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

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

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

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

Вернуться на верх