ast — 抽象语法树

源代码: Lib/ast.py


The 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, type_param* type_params)
          | AsyncFunctionDef(identifier name, arguments args,
                             stmt* body, expr* decorator_list, expr? returns,
                             string? type_comment, type_param* type_params)

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

          | Delete(expr* targets)
          | Assign(expr* targets, expr value, string? type_comment)
          | TypeAlias(expr name, type_param* type_params, expr value)
          | AugAssign(expr target, operator op, expr value)
          -- 'simple' indicates that we annotate simple name without parens
          | AnnAssign(expr target, expr annotation, expr? value, int simple)

          -- use 'orelse' because else is a keyword in target languages
          | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
          | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
          | While(expr test, stmt* body, stmt* orelse)
          | If(expr test, stmt* body, stmt* orelse)
          | With(withitem* items, stmt* body, string? type_comment)
          | AsyncWith(withitem* items, stmt* body, string? type_comment)

          | Match(expr subject, match_case* cases)

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

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

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

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

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

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

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

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

    expr_context = Load | Store | Del

    boolop = And | Or

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

    unaryop = Invert | Not | UAdd | USub

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

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

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

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

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

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

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

    withitem = (expr context_expr, expr? optional_vars)

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

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

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

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

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

    type_ignore = TypeIgnore(int lineno, string tag)

    type_param = TypeVar(identifier name, expr? bound)
               | ParamSpec(identifier name)
               | TypeVarTuple(identifier name)
               attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
}

节点类

class ast.AST

这是所有 AST 节点类的基类。实际的节点类是从 Parser/Python.asdl 文件派生的,该文件在 上面 进行了复制。它们在 _ast C 模块中定义,并在 ast 中重新导出。

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

_fields

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

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

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

lineno
col_offset
end_lineno
end_col_offset

ast.exprast.stmt 子类的实例具有 linenocol_offsetend_linenoend_col_offset 属性。The 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 版本中删除。在此期间,实例化它们将返回一个不同类的实例。

注意

此处显示的特定节点类的描述最初改编自出色的 Green Tree Snakes 项目及其所有贡献者。

根节点

class ast.Module(body, type_ignores)

一个 Python 模块,与 文件输入 相同。在默认的 "exec" 模式中,由 ast.parse() 生成的节点类型。

body 是模块的 语句list

type_ignores 是模块类型忽略注释的 list;有关更多详细信息,请参见 ast.parse()

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

单个 Python 表达式输入。当 mode"eval" 时,由 ast.parse() 生成的节点类型。

body 是单个节点,是 表达式类型 之一。

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

单个 交互式输入,如 交互模式。当 mode"single" 时,由 ast.parse() 生成的节点类型。

bodylist语句节点

>>> print(ast.dump(ast.parse('x = 1; y = 2', mode='single'), indent=4))
Interactive(
    body=[
        Assign(
            targets=[
                Name(id='x', ctx=Store())],
            value=Constant(value=1)),
        Assign(
            targets=[
                Name(id='y', ctx=Store())],
            value=Constant(value=2))])
class ast.FunctionType(argtypes, returns)

旧式函数类型注释的表示,因为 3.5 之前的 Python 版本不支持 PEP 484 注释。当 mode"func_type" 时,由 ast.parse() 生成的节点类型。

此类类型注释将如下所示

def sum_two_number(a, b):
    # type: (int, int) -> int
    return a + b

argtypeslist表达式节点

returns 是单个 表达式节点

>>> print(ast.dump(ast.parse('(int, str) -> List[int]', mode='func_type'), indent=4))
FunctionType(
    argtypes=[
        Name(id='int', ctx=Load()),
        Name(id='str', ctx=Load())],
    returns=Subscript(
        value=Name(id='List', ctx=Load()),
        slice=Name(id='int', ctx=Load()),
        ctx=Load()))

在 3.8 版本中添加。

字面量

class ast.Constant(value)

常量值。 Constant 字面量的 value 属性包含它所表示的 Python 对象。表示的值可以是简单类型,例如数字、字符串或 None,但如果所有元素都是常量,也可以是不可变容器类型(元组和冻结集)。

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

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

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

一个集合。 elts 保存表示集合元素的节点列表。

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

一个字典。 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 保存此部分中的其他节点之一,一个 Constant,一个 Name,一个 Lambda,一个 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)

布尔运算,“或”或“与”。 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)

函数调用。 func 是函数,通常是 NameAttribute 对象。参数

  • args 包含按位置传递的参数列表。

  • keywords 包含 keyword 对象列表,表示按关键字传递的参数。

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

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

在 3.8 版本中添加。

下标

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 中的多个节点表示将相同的值赋给每个节点。解包通过将 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 是一个单独的节点,可以是 NameAttributeSubscriptannotation 是注释,例如 ConstantName 节点。 value 是一个可选的单独节点。

simple 始终为 0(表示“复杂”目标)或 1(表示“简单”目标)。“简单”目标仅包含一个 Name 节点,该节点不会出现在括号之间;所有其他目标都被视为复杂目标。只有简单目标会出现在模块和类的 __annotations__ 字典中。

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

>>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis
Module(
    body=[
        AnnAssign(
            target=Name(id='a', ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            value=Constant(value=1),
            simple=0)],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation
Module(
    body=[
        AnnAssign(
            target=Attribute(
                value=Name(id='a', ctx=Load()),
                attr='b',
                ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            simple=0)],
    type_ignores=[])

>>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation
Module(
    body=[
        AnnAssign(
            target=Subscript(
                value=Name(id='a', ctx=Load()),
                slice=Constant(value=1),
                ctx=Store()),
            annotation=Name(id='int', ctx=Load()),
            simple=0)],
    type_ignores=[])
class ast.AugAssign(target, op, value)

增强赋值,例如 a += 1。在以下示例中,targetxName 节点(带有 Store 上下文),opAdd,而 value 是一个值为 1 的 Constant

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)

一个 raise 语句。 exc 是要引发的异常对象,通常是 CallName,或者对于独立的 raise 则是 Nonecauseraise 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=[])
class ast.TypeAlias(name, type_params, value)

通过 类型别名 创建的 type 语句。 name 是别名的名称,type_params类型参数 的列表,value 是类型别名的值。

>>> print(ast.dump(ast.parse('type Alias = int'), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[],
            value=Name(id='int', ctx=Load()))],
    type_ignores=[])

在 3.12 版本中添加。

其他仅在函数或循环内部适用的语句将在其他部分描述。

导入

class ast.Import(names)

导入语句。 namesalias 节点的列表。

>>> 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” 名称的原始字符串,不包含任何前导点,或对于 from . import foo 这样的语句,则为 Nonelevel 是一个整数,表示相对导入的级别(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 中没有特殊表示,而是作为前一个子句的 orelse 部分中的额外 If 节点出现。

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

一个 for 循环。 target 包含循环分配给的变量,作为单个 NameTupleListAttributeSubscript 节点。 iter 包含要循环遍历的项目,同样作为单个节点。 bodyorelse 包含要执行的节点列表。如果循环正常结束,而不是通过 break 语句结束,则执行 orelse 中的节点。

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)

后面跟着 except* 子句的 try 块。属性与 Try 相同,但 handlers 中的 ExceptHandler 节点被解释为 except* 块,而不是 except

>>> print(ast.dump(ast.parse("""
... try:
...    ...
... except* Exception:
...    ...
... """), indent=4))
Module(
    body=[
        TryStar(
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            handlers=[
                ExceptHandler(
                    type=Name(id='Exception', ctx=Load()),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])],
            orelse=[],
            finalbody=[])],
    type_ignores=[])

在 3.11 版本中添加。

class ast.ExceptHandler(type, name, body)

单个 except 子句。 type 是它将匹配的异常类型,通常是 Name 节点(或用于捕获所有异常的 except: 子句的 None)。 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_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.Match(subject, cases)

一个 match 语句。 subject 保存匹配的主题(与案例匹配的对象),cases 包含一个 match_case 节点可迭代对象,包含不同的案例。

在版本 3.10 中添加。

class ast.match_case(pattern, guard, body)

一个 match 语句中的单个案例模式。 pattern 包含主题将与之匹配的匹配模式。请注意,为模式生成的 AST 节点与为表达式生成的节点不同,即使它们共享相同的语法。

如果模式与主题匹配,则 guard 属性包含一个将被评估的表达式。

body 包含一个节点列表,如果模式匹配并且评估保护表达式结果为真,则执行这些节点。

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

在版本 3.10 中添加。

class ast.MatchValue(value)

一个通过相等比较的匹配文字或值模式。 value 是一个表达式节点。允许的值节点在匹配语句文档中有所限制。如果匹配主题等于评估的值,则此模式成功。

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

在版本 3.10 中添加。

class ast.MatchSingleton(value)

一个通过身份比较的匹配文字模式。 value 是要比较的单例:NoneTrueFalse。如果匹配主题是给定的常量,则此模式成功。

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

在版本 3.10 中添加。

class ast.MatchSequence(patterns)

一个匹配序列模式。 patterns 包含要与主题元素匹配的模式,如果主题是序列。如果其中一个子模式是 MatchStar 节点,则匹配可变长度序列,否则匹配固定长度序列。

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

在版本 3.10 中添加。

class ast.MatchStar(name)

在可变长度匹配序列模式中匹配序列的其余部分。如果 name 不是 None,则如果总体序列模式成功,则将包含剩余序列元素的列表绑定到该名称。

>>> print(ast.dump(ast.parse("""
... match x:
...     case [1, 2, *rest]:
...         ...
...     case [*_]:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchValue(
                                value=Constant(value=1)),
                            MatchValue(
                                value=Constant(value=2)),
                            MatchStar(name='rest')]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchSequence(
                        patterns=[
                            MatchStar()]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

在版本 3.10 中添加。

class ast.MatchMapping(keys, patterns, rest)

一个匹配映射模式。 keys 是表达式节点的序列。 patterns 是相应的模式节点序列。 rest 是一个可选名称,可以指定它来捕获剩余的映射元素。允许的键表达式在匹配语句文档中有所限制。

如果主题是映射,所有评估的键表达式都存在于映射中,并且与每个键相对应的值与相应的子模式匹配,则此模式成功。如果 rest 不是 None,则如果总体映射模式成功,则将包含剩余映射元素的字典绑定到该名称。

>>> print(ast.dump(ast.parse("""
... match x:
...     case {1: _, 2: _}:
...         ...
...     case {**rest}:
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchMapping(
                        keys=[
                            Constant(value=1),
                            Constant(value=2)],
                        patterns=[
                            MatchAs(),
                            MatchAs()]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchMapping(keys=[], patterns=[], rest='rest'),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

在版本 3.10 中添加。

class ast.MatchClass(cls, patterns, kwd_attrs, kwd_patterns)

一个匹配类模式。 cls 是一个表达式,给出要匹配的名义类。 patterns 是一个模式节点序列,要与为类定义的模式匹配属性序列匹配。 kwd_attrs 是一个要匹配的附加属性序列(在类模式中指定为关键字参数),kwd_patterns 是相应的模式(在类模式中指定为关键字值)。

如果主题是提名类的实例,所有位置模式都与相应的类定义属性匹配,并且任何指定的关键字属性都与其相应的模式匹配,则此模式成功。

注意:类可以定义一个返回 self 的属性,以便将模式节点与正在匹配的实例匹配。几个内置类型也以这种方式匹配,如匹配语句文档中所述。

>>> print(ast.dump(ast.parse("""
... match x:
...     case Point2D(0, 0):
...         ...
...     case Point3D(x=0, y=0, z=0):
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='Point2D', ctx=Load()),
                        patterns=[
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0))],
                        kwd_attrs=[],
                        kwd_patterns=[]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))]),
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='Point3D', ctx=Load()),
                        patterns=[],
                        kwd_attrs=[
                            'x',
                            'y',
                            'z'],
                        kwd_patterns=[
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0))]),
                    body=[
                        Expr(
                            value=Constant(value=Ellipsis))])])],
    type_ignores=[])

在版本 3.10 中添加。

class ast.MatchAs(pattern, name)

一个匹配“as-pattern”、捕获模式或通配符模式。 pattern 包含主题将与之匹配的匹配模式。如果模式是 None,则该节点表示捕获模式(即一个裸名称)并且将始终成功。

如果模式成功,则 name 属性包含将被绑定的名称。如果 nameNone,则 pattern 也必须是 None,并且该节点表示通配符模式。

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

在版本 3.10 中添加。

class ast.MatchOr(patterns)

匹配“或模式”。或模式依次将每个子模式与主题匹配,直到其中一个成功。然后,或模式被认为成功。如果所有子模式均未成功,则或模式失败。 patterns 属性包含一个匹配模式节点列表,这些节点将与主题匹配。

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

在版本 3.10 中添加。

类型参数

类型参数 可以存在于类、函数和类型别名中。

class ast.TypeVar(name, bound)

一个 typing.TypeVarname 是类型变量的名称。 bound 是绑定或约束(如果有)。如果 bound 是一个 Tuple,它表示约束;否则它表示绑定。

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

在 3.12 版本中添加。

class ast.ParamSpec(name)

一个 typing.ParamSpecname 是参数规范的名称。

>>> print(ast.dump(ast.parse("type Alias[**P] = Callable[P, int]"), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[
                ParamSpec(name='P')],
            value=Subscript(
                value=Name(id='Callable', ctx=Load()),
                slice=Tuple(
                    elts=[
                        Name(id='P', ctx=Load()),
                        Name(id='int', ctx=Load())],
                    ctx=Load()),
                ctx=Load()))],
    type_ignores=[])

在 3.12 版本中添加。

class ast.TypeVarTuple(name)

一个 typing.TypeVarTuplename 是类型变量元组的名称。

>>> print(ast.dump(ast.parse("type Alias[*Ts] = tuple[*Ts]"), indent=4))
Module(
    body=[
        TypeAlias(
            name=Name(id='Alias', ctx=Store()),
            type_params=[
                TypeVarTuple(name='Ts')],
            value=Subscript(
                value=Name(id='tuple', ctx=Load()),
                slice=Tuple(
                    elts=[
                        Starred(
                            value=Name(id='Ts', ctx=Load()),
                            ctx=Load())],
                    ctx=Load()),
                ctx=Load()))],
    type_ignores=[])

在 3.12 版本中添加。

函数和类定义

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

函数定义。

  • name 是函数名称的原始字符串。

  • args 是一个 arguments 节点。

  • body 是函数内部的节点列表。

  • decorator_list 是要应用的装饰器列表,按最外层优先存储(即列表中的第一个装饰器最后应用)。

  • returns 是返回值注释。

  • type_params类型参数 的列表。

type_comment

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

在 3.12 版本中更改: 添加了 type_params

class ast.Lambda(args, body)

lambda 是一个可以在表达式内部使用的最小函数定义。与 FunctionDef 不同,body 仅包含一个节点。

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

函数的参数。

  • posonlyargsargskwonlyargsarg 节点的列表。

  • varargkwarg 是单个 arg 节点,分别指代 *args, **kwargs 参数。

  • kw_defaults 是关键字参数的默认值列表。如果其中一个是 None,则相应的参数是必需的。

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

class ast.arg(arg, annotation, type_comment)

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

type_comment

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

>>> print(ast.dump(ast.parse("""\
... @decorator1
... @decorator2
... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation':
...     pass
... """), indent=4))
Module(
    body=[
        FunctionDef(
            name='f',
            args=arguments(
                posonlyargs=[],
                args=[
                    arg(
                        arg='a',
                        annotation=Constant(value='annotation')),
                    arg(arg='b'),
                    arg(arg='c')],
                vararg=arg(arg='d'),
                kwonlyargs=[
                    arg(arg='e'),
                    arg(arg='f')],
                kw_defaults=[
                    None,
                    Constant(value=3)],
                kwarg=arg(arg='g'),
                defaults=[
                    Constant(value=1),
                    Constant(value=2)]),
            body=[
                Pass()],
            decorator_list=[
                Name(id='decorator1', ctx=Load()),
                Name(id='decorator2', ctx=Load())],
            returns=Constant(value='return annotation'),
            type_params=[])],
    type_ignores=[])
class ast.Return(value)

一个 return 语句。

>>> print(ast.dump(ast.parse('return 4'), indent=4))
Module(
    body=[
        Return(
            value=Constant(value=4))],
    type_ignores=[])
class ast.Yield(value)
class ast.YieldFrom(value)

一个 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, body, decorator_list, type_params)

类定义。

  • name 是类名称的原始字符串

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

  • keywords 是一个 keyword 节点的列表,主要用于 'metaclass'。其他关键字将根据 PEP-3115 传递给元类。

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

  • decorator_list 是一个节点列表,与 FunctionDef 中的相同。

  • type_params类型参数 的列表。

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

在 3.12 版本中更改: 添加了 type_params

异步和等待

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

一个 async def 函数定义。具有与 FunctionDef 相同的字段。

在 3.12 版本中更改: 添加了 type_params

class ast.Await(value)

一个 await 表达式。 value 是它等待的内容。仅在 AsyncFunctionDef 的主体中有效。

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

async for 循环和 async with 上下文管理器。它们具有与 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() 的标志中。这将报告放置错误的类型注释的语法错误。没有此标志,类型注释将被忽略,并且选定 AST 节点上的 type_comment 字段将始终为 None。此外,# type: ignore 注释的位置将作为 Moduletype_ignores 属性返回(否则它始终为空列表)。

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

feature_version 设置为元组 (major, minor) 将导致“尽力而为”地尝试使用该 Python 版本的语法进行解析。例如,将 feature_version=(3, 9) 设置为将尝试禁止解析 match 语句。目前 major 必须等于 3。最低支持版本为 (3, 4)(这可能会在未来的 Python 版本中增加);最高版本为 sys.version_info[0:2]。“尽力而为”尝试意味着不能保证解析(或解析成功)与在与 feature_version 相对应的 Python 版本上运行时相同。

如果 source 包含空字符 (\0),则会引发 ValueError

警告

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

特别是,ast.parse() 不会执行任何作用域检查,而编译步骤会执行。

警告

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

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

ast.unparse(ast_obj)

反解析 ast.AST 对象并生成一个字符串,其中包含代码,如果使用 ast.parse() 重新解析,该代码将生成等效的 ast.AST 对象。

警告

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

警告

尝试解析高度复杂的表达式会导致 RecursionError

在 3.9 版本中添加。

ast.literal_eval(node_or_string)

评估表达式节点或仅包含 Python 字面量或容器显示的字符串。提供的字符串或节点只能包含以下 Python 字面量结构:字符串、字节、数字、元组、列表、字典、集合、布尔值、NoneEllipsis

这可用于评估包含 Python 值的字符串,而无需自行解析这些值。它无法评估任意复杂的表达式,例如涉及运算符或索引的表达式。

此函数过去曾被记录为“安全”,但没有定义其含义。这是误导性的。此函数专门设计为不执行 Python 代码,与更通用的 eval() 不同。没有命名空间,没有名称查找,也不能调用外部函数。但它并非没有攻击风险:相对较小的输入会导致内存耗尽或 C 栈耗尽,从而使进程崩溃。某些输入也可能导致过度 CPU 消耗,从而造成拒绝服务攻击。因此,不建议在不受信任的数据上调用此函数。

警告

由于 Python 的 AST 编译器中的栈深度限制,可能会导致 Python 解释器崩溃。

它可能会根据格式错误的输入引发 ValueErrorTypeErrorSyntaxErrorMemoryErrorRecursionError

3.2 版本中的变更: 现在允许字节和集合字面量。

3.9 版本中的变更: 现在支持使用 'set()' 创建空集合。

3.10 版本中的变更: 对于字符串输入,现在会去除开头的空格和制表符。

ast.get_docstring(node, clean=True)

返回给定 node 的文档字符串(必须是 FunctionDefAsyncFunctionDefClassDefModule 节点),如果它没有文档字符串,则返回 None。如果 clean 为 True,则使用 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)

如果可能,将源位置(linenocol_offsetend_linenoend_col_offset)从 old_node 复制到 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()或自己访问它们。

visit_Constant(node)

处理所有常量节点。

如果您想在遍历期间对节点进行更改,请不要使用NodeVisitor。为此,存在一个特殊的访问器(NodeTransformer),它允许修改。

自版本 3.8 起弃用: 方法visit_Num()visit_Str()visit_Bytes()visit_NameConstant()visit_Ellipsis()现在已弃用,并且在未来的 Python 版本中不会被调用。添加visit_Constant()方法来处理所有常量节点。

class ast.NodeTransformer

一个NodeVisitor子类,它遍历抽象语法树并允许修改节点。

NodeTransformer将遍历 AST 并使用访问器方法的返回值来替换或删除旧节点。如果访问器方法的返回值为None,则该节点将从其位置删除,否则它将被返回值替换。返回值可能是原始节点,在这种情况下不会进行替换。

以下是一个将所有名称查找(foo)重写为data['foo']的示例转换器

class RewriteName(NodeTransformer):

    def visit_Name(self, node):
        return Subscript(
            value=Name(id='data', ctx=Load()),
            slice=Constant(value=node.id),
            ctx=node.ctx
        )

请记住,如果您正在操作的节点具有子节点,您必须自己转换子节点或首先对节点调用generic_visit()方法。

对于属于语句集合的节点(适用于所有语句节点),访问器也可以返回节点列表,而不仅仅是单个节点。

如果NodeTransformer引入了新的节点(不是原始树的一部分)而没有为它们提供位置信息(例如lineno),则应使用新子树调用fix_missing_locations()来重新计算位置信息

tree = ast.parse('foo', mode='eval')
new_tree = fix_missing_locations(RewriteName().visit(tree))

通常您像这样使用转换器

node = YourTransformer().visit(node)
ast.dump(node, annotate_fields=True, include_attributes=False, *, indent=None)

返回node中树的格式化转储。这主要用于调试目的。如果annotate_fields为真(默认情况下),则返回的字符串将显示字段的名称和值。如果annotate_fields为假,则结果字符串将通过省略明确的字段名称而更加紧凑。默认情况下不会转储诸如行号和列偏移量之类的属性。如果需要,可以将include_attributes设置为真。

如果indent是一个非负整数或字符串,则树将使用该缩进级别进行美化打印。缩进级别为 0、负数或""将只插入换行符。None(默认值)选择单行表示。使用正整数缩进将每级缩进那么多空格。如果indent是一个字符串(例如"\t"),则该字符串将用于缩进每一级。

在版本 3.9 中更改: 添加了indent选项。

编译器标志

以下标志可以传递给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>

指定要编译的代码类型,类似于 parse() 中的 mode 参数。

--no-type-comments

不解析类型注释。

-a, --include-attributes

包含属性,例如行号和列偏移量。

-i <indent>
--indent <indent>

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

如果指定了 infile,则解析其内容为 AST 并将其转储到 stdout。否则,内容将从 stdin 读取。

另请参阅

Green Tree Snakes,一个外部文档资源,详细介绍了使用 Python AST 的方法。

ASTTokens 使用生成它们的源代码中的标记位置和文本对 Python AST 进行注释。这对于进行源代码转换的工具很有帮助。

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

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

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