ast — 抽象语法树

源代码: Lib/ast.py


ast 模块帮助 Python 程序处理 Python 语法的抽象语法树。抽象语法或许会随着 Python 的更新发布而改变;该模块能够帮助理解当前语法在编程层面的样貌。

抽象语法树可通过将 ast.PyCF_ONLY_AST 作为旗标传递给 compile() 内置函数来生成,或是使用此模块中提供的 parse() 辅助函数。返回结果将是一个对象树,其中的类都继承自 ast.AST。抽象语法树可被内置的 compile() 函数编译为一个 Python 代码对象。

抽象文法

抽象文法目前定义如下:

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

          | Match(expr subject, match_case* cases)

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

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

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

          -- col_offset is the byte offset in the utf8 string the parser uses
          attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

          -- BoolOp() can use left & right?
    expr = BoolOp(boolop op, expr* values)
         | NamedExpr(expr target, expr value)
         | BinOp(expr left, operator op, expr right)
         | UnaryOp(unaryop op, expr operand)
         | Lambda(arguments args, expr body)
         | IfExp(expr test, expr body, expr orelse)
         | Dict(expr* keys, expr* values)
         | Set(expr* elts)
         | ListComp(expr elt, comprehension* generators)
         | SetComp(expr elt, comprehension* generators)
         | DictComp(expr key, expr value, comprehension* generators)
         | GeneratorExp(expr elt, comprehension* generators)
         -- the grammar constrains where yield expressions can occur
         | Await(expr value)
         | Yield(expr? value)
         | YieldFrom(expr value)
         -- need sequences for compare to distinguish between
         -- x < 4 < 3 and (x < 4) < 3
         | Compare(expr left, cmpop* ops, expr* comparators)
         | Call(expr func, expr* args, keyword* keywords)
         | FormattedValue(expr value, int conversion, expr? format_spec)
         | JoinedStr(expr* values)
         | Constant(constant value, string? kind)

         -- the following expression can appear in assignment context
         | Attribute(expr value, identifier attr, expr_context ctx)
         | Subscript(expr value, expr slice, expr_context ctx)
         | Starred(expr value, expr_context ctx)
         | Name(identifier id, expr_context ctx)
         | List(expr* elts, expr_context ctx)
         | Tuple(expr* elts, expr_context ctx)

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

          -- col_offset is the byte offset in the utf8 string the parser uses
          attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    expr_context = Load | Store | Del

    boolop = And | Or

    operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
                 | RShift | BitOr | BitXor | BitAnd | FloorDiv

    unaryop = Invert | Not | UAdd | USub

    cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn

    comprehension = (expr target, expr iter, expr* ifs, int is_async)

    excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
                    attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

    arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
                 expr* kw_defaults, arg? kwarg, expr* defaults)

    arg = (identifier arg, expr? annotation, string? type_comment)
           attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)

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

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

    withitem = (expr context_expr, expr? optional_vars)

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

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

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

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

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

    type_ignore = TypeIgnore(int lineno, string tag)
}

节点类

class ast.AST

This is the base of all AST node classes. The actual node classes are derived from the Parser/Python.asdl file, which is reproduced above. They are defined in the _ast C module and re-exported in ast.

抽象语法定义的每个左侧符号(比方说, ast.stmt 或者 ast.expr)定义了一个类。另外,在抽象语法定义的右侧,对每一个构造器也定义了一个类;这些类继承自树左侧的类。比如,ast.BinOp 继承自 ast.expr。对于多分支产生式(也就是”和规则”),树右侧的类是抽象的;只有特定构造器结点的实例能被构造。

_fields

每个具体类都有个属性 _fields, 用来给出所有子节点的名字。

每个具体类的实例对它每个子节点都有一个属性,对应类型如文法中所定义。比如,ast.BinOp 的实例有个属性 left,类型是 ast.expr.

如果这些属性在文法中标记为可选(使用问号),对应值可能会是 None。如果这些属性有零或多个(用星号标记),对应值会用 Python 的列表来表示。所有可能的属性必须在用 compile() 编译得到 AST 时给出,且是有效的值。

lineno
col_offset
end_lineno
end_col_offset

ast.exprast.stmt 子类的实例有 linenocol_offsetend_linenoend_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)

一个常量值。Constant 字面的 value 属性包含它所代表的 Python 对象。所代表的值可以是简单的类型,如数字、字符串或 None,也可以是不可变的容器类型(tuple 和 frozenset),如果它们的所有元素都是常数的话。

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

代表 f-string 中单一格式化字段的节点。如果字符串包含一个单一的格式化字段,而没有其他内容,那么该节点可以被隔离,否则它将出现在 JoinedStr 中。

  • value 是任何表达式节点(如字面值、变量或函数调用)。

  • conversion 是整数:

    • -1:没有格式化

    • 115:!s 字符串格式化

    • 114:!r repr 格式化

    • 97:!a ascii 格式化

  • format_spec 是一个 JoinedStr 节点,代表值的格式化,如果没有指定格式,则为 Noneconversionformat_spec 都可以同时设置。

class ast.JoinedStr(values)

f-string,包括一系列的 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 持有代表其元素的节点列表。如果容器是一个赋值目标(即 (x,y)=something),ctxStore,否则 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)

字典。keysvalues 分别持有代表其键和值的节点列表,顺序匹配(当调用 dictionary.keys()dictionary.values() 时将会返回)。

当使用字典字元进行字典解包时,要展开的表达式在 values 列表中,在 keys 的相应位置有一个 None

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

变量

class ast.Name(id, ctx)

变量名称。id 持有作为字符串的名称,ctx 是以下类型之一。

class ast.Load
class ast.Store
class ast.Del

变量引用可以用来加载变量的值、给它分配新的值或者删除它。变量引用被赋予一个上下文以区分这些情况。

>>> print(ast.dump(ast.parse('a'), indent=4))
Module(
    body=[
        Expr(
            value=Name(id='a', ctx=Load()))],
    type_ignores=[])

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

>>> print(ast.dump(ast.parse('del a'), indent=4))
Module(
    body=[
        Delete(
            targets=[
                Name(id='a', ctx=Del())])],
    type_ignores=[])
class ast.Starred(value, ctx)

*var 的变量引用。value 持有变量,通常是一个 Name 节点。当建立一个带有 *argsCall 节点时,必须使用这种类型。

>>> 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 容纳本节中的一个其他节点,ConstantNameLambdaYieldYieldFrom 节点。

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

一个布尔运算,’or’ 或 ‘and’。opOrAndvalues 是所涉及的值。具有相同操作符的连续操作,如 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 对象的列表,代表由 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.keysvalue 是一个节点,通常是 Nameattr 是一个裸字符串,给出属性的名称,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 节点是由赋值表达式运算符(也被称为海象运算符)产生的。相对于 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 并包含一个 SlicectxLoadStoreDel,根据对下标执行的操作。

>>> 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)。只能出现在 subscriptslice 字段内,可以直接出现,也可以作为 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 中的多个节点代表给每个节点分配相同的值。解包是通过在 targets 内放置一个 TupleList 来表示。

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 是一个单一的节点,可以是 NameAttribute 或一个 Subscriptannotation 是注释,例如 ConstantName 节点。value 是一个单一的可选节点。simple 是一个布尔整数,对于 target 中的 Name 节点,设置为 True,不出现在括号之间,因此是纯名称,不是表达式。

>>> 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。在下面的例子中,targetx 的一个 Name 节点(有 Store 上下文),opAddvalue 是一个 Constant,值为 1。

Assign 的 targets 不同,target 属性不能是 TupleList 类。

>>> 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 是要引发的异常对象,通常是 CallName,或 None 用于独立的 raisecauseraise x from yy 的可选部分。

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

pass 语句。

>>> print(ast.dump(ast.parse('pass'), indent=4))
Module(
    body=[
        Pass()],
    type_ignores=[])

其他只适用于函数或循环内部的语句在其他章节中描述。

Imports

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 ymodule 是 ‘from’ 名称的原始字符串,没有任何前导点,或 None 用于诸如 from . 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 子句在 AST 中没有特殊的表示方法,而是作为额外的 If 节点出现在前一个子句的 orelse 部分。

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

A for loop. target holds the variable(s) the loop assigns to, as a single Name, Tuple, List, Attribute or Subscript node. iter holds the item to be looped over, again as a single node. body and orelse contain lists of nodes to execute. Those in orelse are executed if the loop finishes normally, rather than via a break statement.

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

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.TryStar(body, handlers, orelse, finalbody)

try blocks which are followed by except* clauses. The attributes are the same as for Try but the ExceptHandler nodes in handlers are interpreted as except* blocks rather then 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 是一个原始字符串,用于保存异常的名称,如果子句中没有 as foo,则为 Nonebody 是一个节点的列表。

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

Pattern matching

class ast.Match(subject, cases)

A match statement. subject holds the subject of the match (the object that is being matched against the cases) and cases contains an iterable of match_case nodes with the different cases.

class ast.match_case(pattern, guard, body)

A single case pattern in a match statement. pattern contains the match pattern that the subject will be matched against. Note that the AST nodes produced for patterns differ from those produced for expressions, even when they share the same syntax.

The guard attribute contains an expression that will be evaluated if the pattern matches the subject.

body contains a list of nodes to execute if the pattern matches and the result of evaluating the guard expression is 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)

A match literal or value pattern that compares by equality. value is an expression node. Permitted value nodes are restricted as described in the match statement documentation. This pattern succeeds if the match subject is equal to the evaluated value.

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

A match literal pattern that compares by identity. value is the singleton to be compared against: None, True, or False. This pattern succeeds if the match subject is the given constant.

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

A match sequence pattern. patterns contains the patterns to be matched against the subject elements if the subject is a sequence. Matches a variable length sequence if one of the subpatterns is a MatchStar node, otherwise matches a fixed length sequence.

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

Matches the rest of the sequence in a variable length match sequence pattern. If name is not None, a list containing the remaining sequence elements is bound to that name if the overall sequence pattern is successful.

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

A match mapping pattern. keys is a sequence of expression nodes. patterns is a corresponding sequence of pattern nodes. rest is an optional name that can be specified to capture the remaining mapping elements. Permitted key expressions are restricted as described in the match statement documentation.

This pattern succeeds if the subject is a mapping, all evaluated key expressions are present in the mapping, and the value corresponding to each key matches the corresponding subpattern. If rest is not None, a dict containing the remaining mapping elements is bound to that name if the overall mapping pattern is successful.

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

A match class pattern. cls is an expression giving the nominal class to be matched. patterns is a sequence of pattern nodes to be matched against the class defined sequence of pattern matching attributes. kwd_attrs is a sequence of additional attributes to be matched (specified as keyword arguments in the class pattern), kwd_patterns are the corresponding patterns (specified as keyword values in the class pattern).

This pattern succeeds if the subject is an instance of the nominated class, all positional patterns match the corresponding class-defined attributes, and any specified keyword attributes match their corresponding pattern.

Note: classes may define a property that returns self in order to match a pattern node against the instance being matched. Several builtin types are also matched that way, as described in the match statement documentation.

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

A match “as-pattern”, capture pattern or wildcard pattern. pattern contains the match pattern that the subject will be matched against. If the pattern is None, the node represents a capture pattern (i.e a bare name) and will always succeed.

The name attribute contains the name that will be bound if the pattern is successful. If name is None, pattern must also be None and the node represents the wildcard pattern.

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

A match “or-pattern”. An or-pattern matches each of its subpatterns in turn to the subject, until one succeeds. The or-pattern is then deemed to succeed. If none of the subpatterns succeed the or-pattern fails. The patterns attribute contains a list of match pattern nodes that will be matched against the subject.

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

Function and class definitions

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

A function definition.

  • name is a raw string of the function name.

  • args is an arguments node.

  • body is the list of nodes inside the function.

  • decorator_list is the list of decorators to be applied, stored outermost first (i.e. the first in the list will be applied last).

  • returns is the return annotation.

type_comment

type_comment 是一个可选的字符串,其中的类型注释是一个注释。

class ast.Lambda(args, body)

lambda is a minimal function definition that can be used inside an expression. Unlike FunctionDef, body holds a single node.

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

The arguments for a function.

  • posonlyargs, args and kwonlyargs are lists of arg nodes.

  • vararg and kwarg are single arg nodes, referring to the *args, **kwargs parameters.

  • kw_defaults is a list of default values for keyword-only arguments. If one is None, the corresponding argument is required.

  • defaults is a list of default values for arguments that can be passed positionally. If there are fewer defaults, they correspond to the last n arguments.

class ast.arg(arg, annotation, type_comment)

A single argument in a list. arg is a raw string of the argument name, annotation is its annotation, such as a Str or Name node.

type_comment

type_comment is an optional string with the type annotation as a 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 statement.

>>> 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 yield or yield from expression. Because these are expressions, they must be wrapped in a Expr node if the value sent back is not used.

>>> 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 and nonlocal statements. names is a list of raw strings.

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

A class definition.

  • name is a raw string for the class name

  • bases is a list of nodes for explicitly specified base classes.

  • keywords is a list of keyword nodes, principally for ‘metaclass’. Other keywords will be passed to the metaclass, as per PEP-3115.

  • starargs and kwargs are each a single node, as in a function call. starargs will be expanded to join the list of base classes, and kwargs will be passed to the metaclass.

  • body is a list of nodes representing the code within the class definition.

  • decorator_list is a list of nodes, as in 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=[])

Async and await

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

An async def function definition. Has the same fields as FunctionDef.

class ast.Await(value)

An await expression. value is what it waits for. Only valid in the body of an 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 loops and async with context managers. They have the same fields as For and With, respectively. Only valid in the body of an AsyncFunctionDef.

备注

When a string is parsed by ast.parse(), operator nodes (subclasses of ast.operator, ast.unaryop, ast.cmpop, ast.boolop and ast.expr_context) on the returned tree will be singletons. Changes to one will be reflected in all other occurrences of the same value (e.g. ast.Add).

ast 中的辅助工具

除了节点类, ast 模块里为遍历抽象语法树定义了这些工具函数和类:

ast.parse(source, filename='<unknown>', mode='exec', *, type_comments=False, feature_version=None)

把 source 解析为 AST 节点。和 compile(source, filename, mode,ast.PyCF_ONLY_AST) 等价。

如果给定 type_comments=True,解析器会被修改,以检查并返回 PEP 484PEP 526 所指定的类型注释。这相当于将 ast.PyCF_TYPE_COMMENTS 添加到传递给 compile() 的标志中。这将报告错误的类型注释的语法错误。如果没有这个标志,类型注释将被忽略,选定的 AST 节点上的 type_comment 字段将一直是 None。此外,# type: ignore 注释的位置将作为 Moduletype_ignores 属性返回(否则它总是一个空列表)。

此外,如果 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]

如果 source 包含一个空字符(’0’),ValueError 将被触发。

警告

注意,成功地将源代码解析成 AST 对象并不保证所提供的源代码是可以执行的有效 Python 代码,因为编译步骤可能会引发进一步的 SyntaxError 异常。例如,源码 return 42 为返回语句生成了一个有效的 AST 节点,但它不能被单独编译(它需要在一个函数节点内)。

特别是,ast.parse() 不会做任何范围检查,而编译步骤会做。

警告

足够复杂或是巨大的字符串可能导致 Python 解释器的崩溃,因为 Python 的 AST 编译器是有栈深限制的。

在 3.8 版更改: 增加了 type_commentsmode='func_type'feature_version

ast.unparse(ast_obj)

反向解析 ast.AST 对象,并生成一个字符串,如果用 ast.parse() 解析,将产生一个等价的 ast.AST 对象的代码。

警告

产生的代码字符串不一定等于产生 ast.AST 对象的原始代码(没有任何编译器优化,如常数 tuple/frozenset)。

警告

试图解读一个高度复杂的表达式会导致 RecursionError

3.9 新版功能.

ast.literal_eval(node_or_string)

Evaluate an expression node or a string containing only a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, None and Ellipsis.

This can be used for evaluating strings containing Python values without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.

This function had been documented as “safe” in the past without defining what that meant. That was misleading. This is specifically designed not to execute Python code, unlike the more general eval(). There is no namespace, no name lookups, or ability to call out. But it is not free from attack: A relatively small input can lead to memory exhaustion or to C stack exhaustion, crashing the process. There is also the possibility for excessive CPU consumption denial of service on some inputs. Calling it on untrusted data is thus not recommended.

警告

It is possible to crash the Python interpreter due to stack depth limitations in Python’s AST compiler.

它可能引发 ValueError, TypeError, SyntaxError, MemoryErrorRecursionError ,取决于错误的输入。

在 3.2 版更改: 目前支持字节和集合。

在 3.9 版更改: 现在支持用 'set()' 创建空集合。

在 3.10 版更改: 对于字符串输入,前面的空格和制表符现在被剥离了。

ast.get_docstring(node, clean=True)

返回给定 node 的文档字符串(必须是 FunctionDefAsyncFunctionDefClassDefModule 节点),如果没有文档字符串,则返回 None。如果 clean 为真,则用 inspect.cleandoc() 清理该文档字符串的缩进。

在 3.5 版更改: 目前支持 AsyncFunctionDef

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

获取生成 nodesource 的源代码段。如果某些位置信息(linenoend_linenocol_offsetend_col_offset )丢失,返回 None

如果 paddedTrue,多行语句的第一行将被填充空格,以符合其原始位置。

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)

如果可能的话,从 old_node 复制源位置( linenocol_offsetend_linenoend_col_offset )到 new_node,并返回 new_node

ast.iter_fields(node)

node 上存在的 node._fields 中的每个字段产生一个 (fieldname, value) 的元组。

ast.iter_child_nodes(node)

产生 node 的所有直接子节点,即所有属于节点的字段和属于节点列表的字段的所有项目。

ast.walk(node)

递归产生树中从 node 开始的所有后代节点(包括 node 本身),没有指定顺序。如果你只想就地修改节点,而不关心上下文,这很有用。

class ast.NodeVisitor

一个节点访问者基类,它行走在抽象的语法树上,为每个发现的节点调用一个访问者函数。这个函数可以返回一个值,由 visit() 方法转发。

这个类是要被子类化的,子类会增加访问者方法。

visit(node)

访问一个节点。默认实现是调用 self.visit_classname 的方法,其中 classname 是节点类的名称,如果该方法不存在,则调用 generic_visit()

generic_visit(node)

这个访问者在节点的所有子节点上调用 visit()

注意,拥有自定义访客方法的节点的子节点不会被访问,除非访客调用 generic_visit() 或自己访问它们。

如果你想在遍历过程中对节点进行修改,请不要使用 NodeVisitor。为此,存在一个特殊的访问者(NodeTransformer),允许修改。

3.8 版后已移除: 方法 visit_Num()visit_Str()visit_Bytes()visit_NameConstant()visit_Ellipsis() 现在已经废弃,在未来的 Python 版本中不会被调用。添加 visit_Constant() 方法来处理所有常数节点。

class ast.NodeTransformer

子类 NodeVisitor 用于遍历抽象语法树,并允许修改节点。

NodeTransformer 将遍历抽象语法树并使用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 版更改: 添加 indent 选项。

Compiler Flags

The following flags may be passed to compile() in order to change effects on the compilation of a program:

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

Enables support for top-level await, async for, async with and async comprehensions.

3.8 新版功能.

ast.PyCF_ONLY_AST

Generates and returns an abstract syntax tree instead of returning a compiled code object.

ast.PyCF_TYPE_COMMENTS

Enables support for PEP 484 and PEP 526 style type comments (# type: <type>, # type: ignore <stuff>).

3.8 新版功能.

命令行用法

3.9 新版功能.

The ast module can be executed as a script from the command line. It is as simple as:

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

可以接受以下选项:

-h, --help

Show the help message and exit.

-m <mode>
--mode <mode>

Specify what kind of code must be compiled, like the mode argument in parse().

--no-type-comments

Don’t parse type comments.

-a, --include-attributes

Include attributes such as line numbers and column offsets.

-i <indent>
--indent <indent>

Indentation of nodes in AST (number of spaces).

If infile is specified its contents are parsed to AST and dumped to stdout. Otherwise, the content is read from stdin.

参见

Green Tree Snakes, an external documentation resource, has good details on working with Python ASTs.

ASTTokens annotates Python ASTs with the positions of tokens and text in the source code that generated them. This is helpful for tools that make source code transformations.

leoAst.py unifies the token-based and parse-tree-based views of python programs by inserting two-way links between tokens and ast nodes.

LibCST parses code as a Concrete Syntax Tree that looks like an ast tree and keeps all formatting details. It’s useful for building automated refactoring (codemod) applications and linters.

Parso is a Python parser that supports error recovery and round-trip parsing for different Python versions (in multiple Python versions). Parso is also able to list multiple syntax errors in your python file.