ast ---抽象语法树

源代码: Lib/ast.py


这个 ast 模块帮助python应用程序处理python抽象语法语法树。抽象语法本身可能会随着每个Python版本的变化而变化;这个模块有助于以编程方式找出当前语法的外观。

通过传递可以生成抽象语法树 ast.PyCF_ONLY_AST 作为标志 compile() 内置函数,或使用 parse() 此模块中提供的帮助程序。结果将是所有类都继承自的对象树 ast.AST . 抽象语法树可以使用内置的 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)
          | AsyncFunctionDef(identifier name, arguments args,
                             stmt* body, expr* decorator_list, expr? returns,
                             string? type_comment)

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

          | Delete(expr* targets)
          | Assign(expr* targets, expr value, string? type_comment)
          | AugAssign(expr target, operator op, expr value)
          -- 'simple' 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)

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

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

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

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

    withitem = (expr context_expr, expr? optional_vars)

    type_ignore = TypeIgnore(int lineno, string tag)
}

节点类

class ast.AST

这是所有AST节点类的基础。实际的节点类是从 Parser/Python.asdl 复制的文件 below . 它们在 _ast C模块并在中重新导出 ast .

抽象语法中为每个左侧符号定义了一个类(例如, ast.stmtast.expr )。此外,在右侧为每个构造函数定义了一个类;这些类继承自左侧树的类。例如, ast.BinOp 继承自 ast.expr . 对于具有备选方案的生产规则(也称为“sums”),左侧类是抽象的:只创建特定构造函数节点的实例。

_fields

每个具体类都有一个属性 _fields 它给出了所有子节点的名称。

具体类的每个实例对于每个子节点都有一个属性,属于语法中定义的类型。例如, ast.BinOp 实例具有属性 left 类型的 ast.expr .

如果在语法中将这些属性标记为可选(使用问号),则该值可能是 None . 如果属性可以有零个或多个值(用星号标记),则这些值表示为python列表。使用以下命令编译ast时,所有可能的属性都必须存在并具有有效值 compile() .

lineno
col_offset
end_lineno
end_col_offset

实例 ast.exprast.stmt 子类具有 linenocol_offsetend_lineno ,以及 end_col_offset 属性。这个 linenoend_lineno 是源文本范围的第一个和最后一个行号(1-已编制索引,因此第一行是第1行),而 col_offsetend_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.Numast.Strast.Bytesast.NameConstantast.Ellipsis 仍然可用,但在将来的Python版本中将删除它们。同时,实例化它们将返回一个不同类的实例。

3.9 版后已移除: 旧阶级 ast.Indexast.ExtSlice 仍然可用,但在将来的Python版本中将删除它们。同时,实例化它们将返回一个不同类的实例。

直接常量

class ast.Constant(value)

恒定值。这个 value 的属性 Constant literal包含它所表示的Python对象。所表示的值可以是简单的类型,如数字、字符串或 None ,但也可以是不可变的容器类型(元组和frozensets),前提是它们的所有元素都是常量。

>>> 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 如果没有指定格式。两者 conversionformat_spec 可以同时设置。

class ast.JoinedStr(values)

f字串,包括一系列 FormattedValueConstant 节点。

>>> 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 保存表示元素的节点列表。 ctxStore 如果容器是分配目标(即。 (x,y)=somethingLoad 否则。

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

一本字典。 keysvalues 按匹配顺序保存分别表示键和值的节点列表(调用时将返回什么 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)

A *var 变量引用。 value 保存变量,通常是 Name 节点。在生成 Call 节点 *args .

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

表达

class ast.Expr(value)

当一个表达式(如函数调用)本身作为一个语句出现,而其返回值未被使用或存储时,它将被包装在此容器中。 value 保存本节中的其他节点之一 Constant ,A Name ,A Lambda ,A YieldYieldFrom 节点。

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

一元运算符标记。 Notnot 关键字, 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 是接线员,而且 leftright 是任何表达式节点。

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

布尔运算“或”或“和”。 opOrAnd . values 是否涉及价值观。具有相同运算符的连续操作,例如 a or b or c ,将折叠为具有多个值的一个节点。

这不包括 not ,这是一个 UnaryOp .

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

布尔运算符标记。

class ast.Compare(left, ops, comparators)

两个或多个值的比较。 left 是比较中的第一个值, ops 操作员列表,以及 comparators 比较中第一个元素之后的值列表。

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

比较运算符标记。

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

函数调用。 func 是函数,它通常是 NameAttribute 反对。论据:

  • args 保存按位置传递的参数列表。

  • keywords 保存一个列表 keyword 表示关键字传递的参数的对象。

创建一个 Call 节点, argskeywords 是必需的,但它们可以是空列表。 starargskwargs 是可选的。

>>> 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 是一个给出属性名称的裸字符串,并且 ctxLoadStoreDel 根据属性的作用方式。

>>> 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 第一个参数可以是多个节点的节点,在这种情况下 targetvalue 必须是单个节点。

>>> 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 . ctxLoadStoreDel 根据用下标执行的操作。

>>> 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:upperlower:upper:step ). 只能发生在 领域 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 (或) keyvalue )是表示将为每个项计算的部分的单个节点。

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 是用于每个元素的引用-通常是 NameTuple 节点。 iter 是要迭代的对象。 ifs 是测试表达式的列表:每个 for 子句可以有多个 ifs .

is_async 表示理解是异步的(使用 async for 而不是 for ). 该值是一个整数(0或1)。

>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'),
...                indent=4)) # Multiple comprehensions in one.
Expression(
    body=ListComp(
        elt=Call(
            func=Name(id='ord', ctx=Load()),
            args=[
                Name(id='c', ctx=Load())],
            keywords=[]),
        generators=[
            comprehension(
                target=Name(id='line', ctx=Store()),
                iter=Name(id='file', ctx=Load()),
                ifs=[],
                is_async=0),
            comprehension(
                target=Name(id='c', ctx=Store()),
                iter=Name(id='line', ctx=Load()),
                ifs=[],
                is_async=0)]))

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

>>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'),
...                indent=4)) # Async comprehension
Expression(
    body=ListComp(
        elt=Name(id='i', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='i', ctx=Store()),
                iter=Name(id='soc', ctx=Load()),
                ifs=[],
                is_async=1)]))

声明

class ast.Assign(targets, value, type_comment)

任务。 targets 是一个节点列表,并且 value 是单个节点。

中的多个节点 targets 表示为每个分配相同的值。解包是通过放置 TupleList 在内部 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 ,A Attribute 或A Subscript . annotation 是注释,例如 ConstantName 节点。 value 是单个可选节点。 simple 对于 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 上下文), opAddvalue 是一个 Constant 值为1。

这个 target 属性不属于类 TupleList ,不同于 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)

A raise 语句。 exc 是要引发的异常对象,通常是 CallNameNone 对于独立的 raise . causey 在里面 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 是节点的列表,例如 NameAttributeSubscript 节点。

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

A 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 节点。 bodyorelse 每个节点都有一个节点列表。

elif 子句在as t中没有特殊的表示,而是作为额外的 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)

A for 循环。 target 将循环分配给的变量作为单个变量保存 NameTupleList 节点。 iter 保存要循环的项,再次作为单个节点。 bodyorelse 包含要执行的节点列表。那些在 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)

A 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

这个 breakcontinue 声明。

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

try 阻碍。所有属性都是要执行的节点列表,除了 handlers ,这是一个列表 ExceptHandler 节点。

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

单一的 except 条款。 type 是它将匹配的异常类型,通常是 Name 节点(或 None 为了一网打尽 except: 条款)。 name 是用于保存异常的名称的原始字符串,或 None 如果条款没有 as foo . body 是节点列表。

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

A with 块。 items 是一个列表 withitem 表示上下文管理器的节点,以及 body 是上下文中的缩进块。

type_comment

type_comment 是一个可选字符串,类型批注作为注释。

class ast.withitem(context_expr, optional_vars)

中的单个上下文管理器 with 块。 context_expr 是上下文管理器,通常是 Call 节点。 optional_vars 是一个 NameTupleList 对于 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.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 是可以在表达式内部使用的最小函数定义。不像 FunctionDefbody 包含单个节点。

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

函数的参数。

  • posonlyargsargskwonlyargsarg 节点。

  • varargkwarg 都是单身 arg 节点,指 *args, **kwargs 参数。

  • kw_defaults 是仅关键字参数的默认值列表。如果是的话 None ,则需要相应的参数。

  • defaults 是可按位置传递的参数的默认值列表。如果默认值较少,则它们对应于最后n个参数。

class ast.arg(arg, annotation, type_comment)

列表中的单个参数。 arg 是参数名的原始字符串, annotation 是它的注释,例如 StrName 节点。

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)

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

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

globalnonlocal 声明。 names 是原始字符串的列表。

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

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

类定义。

  • name 是类名的原始字符串

  • bases 是显式指定基类的节点列表。

  • keywords 是一个列表 keyword 节点,主要用于“元类”。其他关键字将根据 PEP-3115 .

  • starargskwargs 每个节点都是单个节点,如在函数调用中。starargs将被扩展以加入基类列表,kwargs将被传递给元类。

  • body 是表示类定义中代码的节点列表。

  • decorator_list 是节点列表,如 FunctionDef .

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

异步等待

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 上下文管理器。它们与 ForWith ,分别是。仅在 AsyncFunctionDef .

注解

当字符串由 ast.parse() ,运算符节点(的子类 ast.operatorast.unaryopast.cmpopast.boolopast.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 484PEP 526 . 这相当于添加 ast.PyCF_TYPE_COMMENTS 传递给 compile() . 这将报告错误放置的类型注释的语法错误。如果没有此标志,类型注释将被忽略,并且 type_comment 所选AST节点上的字段将始终为 None . 此外,在 # type: ignore 注释将作为 type_ignores 属性 Module (否则,它总是一个空列表)。

此外,如果 mode'func_type' ,修改输入语法以对应 PEP 484 “签名类型注释”,例如 (str, int) -> List[str] .

此外,设置 feature_version 到一个元组 (major, minor) 将尝试使用该Python版本的语法进行分析。目前 major 必须等于 3 . 例如,设置 feature_version=(3, 4) 将允许使用 asyncawait 作为变量名。支持的最低版本是 (3, 4) 最高的是 sys.version_info[0:2] .

警告

由于Python的AST编译器中的堆栈深度限制,使用足够大/复杂的字符串可能会导致Python解释器崩溃。

在 3.8 版更改: 补充 type_commentsmode='func_type'feature_version .

ast.unparse(ast_obj)

拆开 ast.AST 对象并生成一个字符串,该字符串的代码将生成等效的 ast.AST 对象,如果用 ast.parse() .

警告

生成的代码字符串不一定等于生成 ast.AST 对象(没有任何编译器优化,例如常量元组/冻结集)。

警告

试图拆开高度复杂的表达式将导致 RecursionError .

3.9 新版功能.

ast.literal_eval(node_or_string)

安全地计算包含Python文字或容器显示的表达式节点或字符串。所提供的字符串或节点可以仅由以下Python文字结构组成:字符串、字节、数字、元组、列表、字典、集合、布尔值, NoneEllipsis

这可以用于安全地评估包含来自不受信任源的python值的字符串,而无需自己解析这些值。它不能计算任意复杂的表达式,例如涉及运算符或索引。

警告

由于Python的AST编译器中的堆栈深度限制,使用足够大/复杂的字符串可能会导致Python解释器崩溃。

它可以提高 ValueErrorTypeErrorSyntaxErrorMemoryErrorRecursionError 取决于格式错误的输入。

在 3.2 版更改: 现在允许字节和设置文本。

在 3.9 版更改: 现在支持使用 'set()' .

在 3.10 版更改: 对于字符串输入,现在去掉了前导空格和制表符。

ast.get_docstring(node, clean=True)

返回给定的文档字符串 node (必须是 FunctionDefAsyncFunctionDefClassDefModule 节点) None 如果没有docstring。如果 清洁的 是真的,用 inspect.cleandoc() .

在 3.5 版更改: AsyncFunctionDef 现在支持。

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

获取的源代码段 source 产生的 node . 如果一些位置信息 (linenoend_linenocol_offsetend_col_offset )丢失,返回 None .

如果 衬垫True ,多行语句的第一行将用空格填充,以匹配其原始位置。

3.8 新版功能.

ast.fix_missing_locations(node)

编译节点树时, compile() ,编译器期望 linenocol_offset 支持它们的每个节点的属性。对于生成的节点,这相当繁琐,因此这个助手通过将这些属性设置为父节点的值,递归地将这些属性添加到尚未设置的位置。它以递归方式从 node .

ast.increment_lineno(node, n=1)

从开始增加树中每个节点的行号和结束行号 node 通过 n . 这对于将代码“移动”到文件中的其他位置很有用。

ast.copy_location(new_node, old_node)

复制源位置 (linenocol_offsetend_linenoend_col_offset )从 old_nodenew_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} 在哪里? 类的名称 是节点类的名称,或者 generic_visit() 如果这个方法不存在。

generic_visit(node)

这个访客调用来 visit() 在节点的所有子节点上。

请注意,除非访问者调用,否则将不会访问具有自定义访问者方法的节点的子节点。 generic_visit() 或者亲自拜访他们。

不要使用 NodeVisitor 如果要在遍历期间将更改应用于节点。为此,有一个特殊的访客 (NodeTransformer )允许修改。

3.8 版后已移除: 方法 visit_Num()visit_Str()visit_Bytes()visit_NameConstant()visit_Ellipsis() 现在不推荐使用,以后的Python版本中将不会调用。添加 visit_Constant() 方法来处理所有常量节点。

class ast.NodeTransformer

A NodeVisitor 遍历抽象语法树并允许修改节点的子类。

这个 NodeTransformer 将遍历ast并使用visitor方法的返回值来替换或删除旧节点。如果visitor方法的返回值为 None ,节点将从其位置移除,否则将替换为返回值。返回值可以是原始节点,在这种情况下不会发生替换。

下面是一个示例转换器,它重写所有出现的名称查找 (foodata['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 引入新节点(不是原始树的一部分),而不向它们提供位置信息(例如 linenofix_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。

如果 缩进 是一个非负整数或字符串,则树将以该缩进级别漂亮地打印出来。缩进级别为0、负或 "" 只插入换行符。 None (默认设置)选择单线表示。使用正整数缩进可使每个级别缩进多个空格。如果 缩进 是字符串(例如 "\t" ,该字符串用于缩进每个级别。

在 3.9 版更改: 增加了 缩进 选择权。

编译器标志

可以将以下标志传递给 compile() 要更改对程序编译的影响,请执行以下操作:

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

启用对顶层的支持 awaitasync forasync with 和异步理解。

3.8 新版功能.

ast.PyCF_ONLY_AST

生成并返回抽象语法树,而不是返回已编译的代码对象。

ast.PyCF_TYPE_COMMENTS

启用对以下各项的支持 PEP 484PEP 526 样式类型注释 (# type: <type># type: ignore <stuff> )。

3.8 新版功能.

命令行用法

3.9 新版功能.

这个 ast 模块可以作为脚本从命令行执行。它简单如下:

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

接受以下选项:

-h, --help

显示帮助消息并退出。

-m <mode>
--mode <mode>

指定必须编译的代码类型,如 mode 论点 parse() .

--no-type-comments

不要分析类型注释。

-a, --include-attributes

包括行号和列偏移等属性。

-i <indent>
--indent <indent>

AST中节点的缩进(空格数)。

如果 infile 它的内容被解析为AST并转储到stdout。否则,将从stdin读取内容。

参见

Green Tree Snakes <https://greentreesnakes.readthedocs.io/> _作为一个外部文档资源,它对使用Python AST有很好的细节。

ASTTokens 用生成标记的源代码中的标记和文本的位置来注释pythonast。这对于进行源代码转换的工具非常有用。

leoAst.py 通过在令牌和ast节点之间插入双向链接,统一了python程序的基于令牌和基于解析树的视图。

LibCST 将代码解析为一个具体的语法树,该树看起来像ast树,并保留所有格式详细信息。它对于构建自动重构(codemod)应用程序和linter非常有用。

Parso 是一个Python解析器,支持不同Python版本(在多个Python版本中)的错误恢复和往返解析。Parso还可以在python文件中列出多个语法错误。