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, 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)
         | Interpolation(expr value, constant str, int conversion, expr? format_spec)
         | JoinedStr(expr* values)
         | TemplateStr(expr* values)
         | Constant(constant value, string? kind)

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

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

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

    expr_context = Load | Store | Del

    boolop = And | Or

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

    unaryop = Invert | Not | UAdd | USub

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

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

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

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

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

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

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

    withitem = (expr context_expr, expr? optional_vars)

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

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

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

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

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

    type_ignore = TypeIgnore(int lineno, string tag)

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

节点类

class ast.AST

这是所有 AST 节点类的基类。实际的节点类派生自 Parser/Python.asdl 文件,该文件在上方有转载。它们定义在 _ast C 模块中,并在 ast 中重新导出。

抽象语法中每个左侧符号都有一个定义的类(例如,ast.stmtast.expr)。此外,右侧的每个构造器也都有一个定义的类;这些类继承自左侧树的类。例如,ast.BinOp 继承自 ast.expr。对于带有备选项(即“和类型”)的产生式规则,左侧的类是抽象的:只有特定构造器节点的实例会被创建。

_fields

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

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

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

_field_types

每个具体类上的 _field_types 属性是一个字典,将字段名(也列在 _fields 中)映射到它们的类型。

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

在 3.13 版本加入。

lineno
col_offset
end_lineno
end_col_offset

ast.exprast.stmt 子类的实例具有 linenocol_offsetend_linenoend_col_offset 属性。linenoend_lineno 是源代码文本范围的第一行和最后一行行号(1-indexed,所以第一行是第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(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
                   lineno=0, col_offset=0)

如果构造函数中省略了在语法中为可选的字段,则其默认值为 None。如果省略了列表字段,则其默认值为空列表。如果省略了类型为 ast.expr_context 的字段,则其默认值为 Load()。如果省略任何其他字段,将引发 DeprecationWarning,并且 AST 节点将不包含此字段。在 Python 3.15 中,这种情况将引发错误。

在 3.8 版更改: ast.Constant 现在用于所有常量。

在 3.9 版更改: 简单索引由其值表示,扩展切片由元组表示。

在 3.14 版更改: AST 节点的 __repr__() 输出包括节点字段的值。

自 3.8 版起不推荐使用: 旧的类 ast.Numast.Strast.Bytesast.NameConstantast.Ellipsis 仍然可用,但它们将在未来的 Python 版本中被移除。在此期间,实例化它们将返回一个不同类的实例。

自 3.9 版起不推荐使用: 旧的类 ast.Indexast.ExtSlice 仍然可用,但它们将在未来的 Python 版本中被移除。在此期间,实例化它们将返回一个不同类的实例。

自 3.13 版起不推荐使用,将在 3.15 版中移除: 旧版本的 Python 允许创建缺少必需字段的 AST 节点。类似地,AST 节点构造函数允许任意关键字参数,这些参数被设置为 AST 节点的属性,即使它们不匹配 AST 节点的任何字段。此行为已弃用,并将在 Python 3.15 中移除。

备注

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

根节点

class ast.Module(body, type_ignores)

一个 Python 模块,如同文件输入一样。在默认的 "exec" mode 下,由 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))])
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() 生成的节点类型。

body 是一个list,包含语句节点

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

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

这类类型注释看起来是这样的:

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

argtypes 是一个包含表达式节点list

returns 是一个单独的表达式节点

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

在 3.8 版本加入。

字面值

class ast.Constant(value)

一个常量值。Constant 字面值的 value 属性包含它所代表的 Python 对象。所代表的值可以是 strbytesintfloatcomplexbool 的实例,以及常量 NoneEllipsis

>>> 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: 无格式化

    • 97 (ord('a')): !a ASCII 格式化

    • 114 (ord('r')): !r repr() 格式化

    • 115 (ord('s')): !s string 格式化

  • 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())]),
                conversion=-1,
                format_spec=JoinedStr(
                    values=[
                        Constant(value='.3')]))]))
class ast.TemplateStr(values, /)

在 3.14 版本加入。

表示模板字符串字面值的节点,由一系列 InterpolationConstant 节点组成。这些节点可以按任何顺序排列,并且不必交错。

>>> expr = ast.parse('t"{name} finished {place:ordinal}"', mode='eval')
>>> print(ast.dump(expr, indent=4))
Expression(
    body=TemplateStr(
        values=[
            Interpolation(
                value=Name(id='name', ctx=Load()),
                str='name',
                conversion=-1),
            Constant(value=' finished '),
            Interpolation(
                value=Name(id='place', ctx=Load()),
                str='place',
                conversion=-1,
                format_spec=JoinedStr(
                    values=[
                        Constant(value='ordinal')]))]))
class ast.Interpolation(value, str, conversion, format_spec=None)

在 3.14 版本加入。

表示模板字符串字面值中单个插值字段的节点。

  • value 是任何表达式节点(例如字面值、变量或函数调用)。其含义与 FormattedValue.value 相同。

  • str 是一个包含插值表达式文本的常量。

  • conversion 是一个整数

    • -1: 无转换

    • 97 (ord('a')): !a ASCII 转换

    • 114 (ord('r')): !r repr() 转换

    • 115 (ord('s')): !s string 转换

    其含义与 FormattedValue.conversion 相同。

  • format_spec 是一个 JoinedStr 节点,表示值的格式,如果未指定格式,则为 Noneconversionformat_spec 可以同时设置。其含义与 FormattedValue.format_spec 相同。

class ast.List(elts, ctx)
class ast.Tuple(elts, ctx)

列表或元组。elts 包含一个表示元素的节点列表。ctx 在容器是赋值目标(即 (x,y)=something)时为 Store,否则为 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()))])

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

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

一个 *var 变量引用。value 保存变量,通常是一个 Name 节点。当构建带 *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()))])

表达式

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

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

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

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

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 是一个给出属性名称的裸字符串,ctx 根据对属性的操作是 LoadStore 还是 Del

>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4))
Expression(
    body=Attribute(
        value=Name(id='snake', ctx=Load()),
        attr='colour',
        ctx=Load()))
class ast.NamedExpr(target, value)

一个命名表达式。这个 AST 节点由赋值表达式运算符(也称为海象运算符)产生。与 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 并且包含一个 Slicectx 根据对下标执行的操作是 LoadStore 还是 Del

>>> print(ast.dump(ast.parse('l[1:2, 3]', mode='eval'), indent=4))
Expression(
    body=Subscript(
        value=Name(id='l', ctx=Load()),
        slice=Tuple(
            elts=[
                Slice(
                    lower=Constant(value=1),
                    upper=Constant(value=2)),
                Constant(value=3)],
            ctx=Load()),
        ctx=Load()))
class ast.Slice(lower, upper, step)

常规切片(形式为 lower: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()),
                is_async=0)]))
>>> print(ast.dump(
...     ast.parse('{x: x**2 for x in numbers}', mode='eval'),
...     indent=4,
... ))
Expression(
    body=DictComp(
        key=Name(id='x', ctx=Load()),
        value=BinOp(
            left=Name(id='x', ctx=Load()),
            op=Pow(),
            right=Constant(value=2)),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                is_async=0)]))
>>> print(ast.dump(
...     ast.parse('{x for x in numbers}', mode='eval'),
...     indent=4,
... ))
Expression(
    body=SetComp(
        elt=Name(id='x', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                is_async=0)]))
class ast.comprehension(target, iter, ifs, is_async)

推导式中的一个 for 子句。target 是用于每个元素的引用 - 通常是 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())]),
        generators=[
            comprehension(
                target=Name(id='line', ctx=Store()),
                iter=Name(id='file', ctx=Load()),
                is_async=0),
            comprehension(
                target=Name(id='c', ctx=Store()),
                iter=Name(id='line', ctx=Load()),
                is_async=0)]))

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

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

语句

class ast.Assign(targets, value, type_comment)

一个赋值语句。targets 是一个节点列表,value 是一个单独的节点。

targets 中的多个节点表示将相同的值赋给每个节点。解包通过在 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))])

>>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking
Module(
    body=[
        Assign(
            targets=[
                Tuple(
                    elts=[
                        Name(id='a', ctx=Store()),
                        Name(id='b', ctx=Store())],
                    ctx=Store())],
            value=Name(id='c', ctx=Load()))])
class ast.AnnAssign(target, annotation, value, simple)

带类型注解的赋值。target 是一个单独的节点,可以是 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)])

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

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

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

增量赋值,例如 a += 1。在下面的例子中,target 是一个代表 xName 节点(带有 Store 上下文),opAddvalue 是一个值为 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))])
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()))])
class ast.Assert(test, msg)

一个断言。test 包含条件,例如 Compare 节点。msg 包含失败消息。

>>> print(ast.dump(ast.parse('assert x,y'), indent=4))
Module(
    body=[
        Assert(
            test=Name(id='x', ctx=Load()),
            msg=Name(id='y', ctx=Load()))])
class ast.Delete(targets)

表示一个 del 语句。targets 是一个节点列表,例如 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())])])
class ast.Pass

一个 pass 语句。

>>> print(ast.dump(ast.parse('pass'), indent=4))
Module(
    body=[
        Pass()])
class ast.TypeAlias(name, type_params, value)

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

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

3.12 新版功能.

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

导入

class ast.Import(names)

一个导入语句。names 是一个 alias 节点列表。

>>> print(ast.dump(ast.parse('import x,y,z'), indent=4))
Module(
    body=[
        Import(
            names=[
                alias(name='x'),
                alias(name='y'),
                alias(name='z')])])
class ast.ImportFrom(module, names, level)

代表 from x import 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)])
class ast.alias(name, asname)

两个参数都是名称的原始字符串。如果使用常规名称,asname 可以为 None

>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4))
Module(
    body=[
        ImportFrom(
            module='foo.bar',
            names=[
                alias(name='a', asname='b'),
                alias(name='c')],
            level=2)])

控制流

备注

else 这样的可选子句如果不存在,则存储为空列表。

class ast.If(test, body, orelse)

一个 if 语句。 test 包含一个节点,例如 Compare 节点。 bodyorelse 各自包含一个节点列表。

elif 子句在 AST 中没有特殊的表示形式,而是作为前一个 If 节点的 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))])])])
class ast.For(target, iter, body, orelse, type_comment)

一个 for 循环。 target 包含循环赋值的变量,可以是单个 Name, Tuple, List, AttributeSubscript 节点。 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))])])
class ast.While(test, body, orelse)

一个 while 循环。 test 包含条件,例如一个 Compare 节点。

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

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()])])])
class ast.Try(body, handlers, orelse, finalbody)

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

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

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

在 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()])])])
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_varsas foo 部分的 NameTupleList 节点,如果未使用该部分则为 None

>>> print(ast.dump(ast.parse("""\
... with a as b, c as d:
...    something(b, d)
... """), indent=4))
Module(
    body=[
        With(
            items=[
                withitem(
                    context_expr=Name(id='a', ctx=Load()),
                    optional_vars=Name(id='b', ctx=Store())),
                withitem(
                    context_expr=Name(id='c', ctx=Load()),
                    optional_vars=Name(id='d', ctx=Store()))],
            body=[
                Expr(
                    value=Call(
                        func=Name(id='something', ctx=Load()),
                        args=[
                            Name(id='b', ctx=Load()),
                            Name(id='d', ctx=Load())]))])])

模式匹配

class ast.Match(subject, cases)

一个 match 语句。 subject 包含匹配的主体(即与各种 case 进行匹配的对象),而 cases 包含一个由 match_case 节点组成的可迭代对象,代表不同的 case。

在 3.10 版本加入。

class ast.match_case(pattern, guard, body)

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

guard 属性包含一个表达式,如果模式匹配成功,该表达式将被求值。

如果模式匹配成功且守卫表达式的求值结果为真,body 包含要执行的节点列表。

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

在 3.10 版本加入。

class ast.MatchValue(value)

一个通过相等性比较的匹配字面值或值模式。 value 是一个表达式节点。允许的值节点受到 match 语句文档中所述的限制。如果匹配主体等于求值后的值,则此模式匹配成功。

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

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

在 3.10 版本加入。

class ast.MatchSequence(patterns)

一个匹配序列模式。如果主体是序列,patterns 包含将与主体元素进行匹配的模式。如果子模式之一是 MatchStar 节点,则匹配可变长度序列,否则匹配固定长度序列。

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

在 3.10 版本加入。

class ast.MatchStar(name)

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

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

在 3.10 版本加入。

class ast.MatchMapping(keys, patterns, rest)

一个匹配映射模式。 keys 是一个表达式节点序列。 patterns 是一个对应的模式节点序列。 rest 是一个可选名称,可用于捕获剩余的映射元素。允许的键表达式受到 match 语句文档中所述的限制。

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

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

在 3.10 版本加入。

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

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

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

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

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

在 3.10 版本加入。

class ast.MatchAs(pattern, name)

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

如果模式成功,name 属性包含将要绑定的名称。如果 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))])])])

在 3.10 版本加入。

class ast.MatchOr(patterns)

一个匹配“or-pattern”。一个 or-pattern 会将其每个子模式依次与主体进行匹配,直到有一个匹配成功。此时,or-pattern 被视为成功。如果所有子模式都匹配失败,则 or-pattern 失败。 patterns 属性包含一个将与主体进行匹配的模式节点列表。

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

在 3.10 版本加入。

类型注解

class ast.TypeIgnore(lineno, tag)

位于 lineno 行的 # type: ignore 注释。 tag 是由 # type: ignore <tag> 形式指定的可选标签。

>>> print(ast.dump(ast.parse('x = 1 # type: ignore', type_comments=True), indent=4))
Module(
    body=[
        Assign(
            targets=[
                Name(id='x', ctx=Store())],
            value=Constant(value=1))],
    type_ignores=[
        TypeIgnore(lineno=1, tag='')])
>>> print(ast.dump(ast.parse('x: bool = 1 # type: ignore[assignment]', type_comments=True), indent=4))
Module(
    body=[
        AnnAssign(
            target=Name(id='x', ctx=Store()),
            annotation=Name(id='bool', ctx=Load()),
            value=Constant(value=1),
            simple=1)],
    type_ignores=[
        TypeIgnore(lineno=1, tag='[assignment]')])

备注

type_comments 参数设置为 False(默认值)时,不会生成 TypeIgnore 节点。更多详情请参阅 ast.parse()

在 3.8 版本加入。

类型形参

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

class ast.TypeVar(name, bound, default_value)

一个 typing.TypeVarname 是类型变量的名称。 bound 是边界或约束(如果有的话)。如果 bound 是一个 Tuple,它代表约束;否则它代表边界。 default_value 是默认值;如果 TypeVar 没有默认值,此属性将被设置为 None

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

3.12 新版功能.

在 3.13 版本发生变更: 添加了 default_value 形参。

class ast.ParamSpec(name, default_value)

一个 typing.ParamSpecname 是参数规范的名称。 default_value 是默认值;如果 ParamSpec 没有默认值,此属性将被设置为 None

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

3.12 新版功能.

在 3.13 版本发生变更: 添加了 default_value 形参。

class ast.TypeVarTuple(name, default_value)

一个 typing.TypeVarTuplename 是类型变量元组的名称。 default_value 是默认值;如果 TypeVarTuple 没有默认值,此属性将被设置为 None

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

3.12 新版功能.

在 3.13 版本发生变更: 添加了 default_value 形参。

函数和类定义

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

一个函数定义。

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

  • args 是一个 arguments 节点。

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

  • decorator_list 是要应用的装饰器列表,按从外到内的顺序存储(即列表中的第一个装饰器将最后应用)。

  • returns 是返回值的注解。

  • type_params 是一个 类型形参 的列表。

type_comment

type_comment 是一个可选字符串,带有作为注释的类型注解。

在 3.12 版本发生变更: 添加了 type_params

class ast.Lambda(args, body)

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

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

函数的参数。

  • posonlyargs, argskwonlyargsarg 节点的列表。

  • 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(
                args=[
                    arg(
                        arg='a',
                        annotation=Constant(value='annotation')),
                    arg(arg='b'),
                    arg(arg='c')],
                vararg=arg(arg='d'),
                kwonlyargs=[
                    arg(arg='e'),
                    arg(arg='f')],
                kw_defaults=[
                    None,
                    Constant(value=3)],
                kwarg=arg(arg='g'),
                defaults=[
                    Constant(value=1),
                    Constant(value=2)]),
            body=[
                Pass()],
            decorator_list=[
                Name(id='decorator1', ctx=Load()),
                Name(id='decorator2', ctx=Load())],
            returns=Constant(value='return annotation'))])
class ast.Return(value)

一个 return 语句。

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

一个 yieldyield from 表达式。因为这些是表达式,如果返回的值不被使用,它们必须被包装在一个 Expr 节点中。

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

>>> print(ast.dump(ast.parse('yield from x'), indent=4))
Module(
    body=[
        Expr(
            value=YieldFrom(
                value=Name(id='x', ctx=Load())))])
class ast.Global(names)
class ast.Nonlocal(names)

globalnonlocal 语句。 names 是原始字符串的列表。

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

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

一个类定义。

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

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

  • keywordskeyword 节点的列表,主要用于‘metaclass’。其他关键字将根据 PEP 3115 传递给元类。

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

  • decorator_list 是节点列表,与 FunctionDef 中一样。

  • type_params 是一个 类型形参 的列表。

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

在 3.12 版本发生变更: 添加了 type_params

Async 和 await

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

一个 async def 函数定义。其字段与 FunctionDef 相同。

在 3.12 版本发生变更: 添加了 type_params

class ast.Await(value)

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

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

async for 循环和 async with 上下文管理器。它们的字段分别与 ForWith 相同。仅在 AsyncFunctionDef 的主体中有效。

备注

当字符串由 ast.parse() 解析时,返回树上的操作符节点(ast.operator, ast.unaryop, ast.cmpop, ast.boolopast.expr_context 的子类)将是单例。对一个的更改将反映在所有其他相同值的出现中(例如,ast.Add)。

ast 辅助函数

除了节点类,ast 模块定义了以下用于遍历抽象语法树的实用函数和类:

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

将源代码解析为 AST 节点。等同于 compile(source, filename, mode, flags=FLAGS_VALUE, optimize=optimize),其中如果 optimize <= 0FLAGS_VALUEast.PyCF_ONLY_AST,否则是 ast.PyCF_OPTIMIZED_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, 7)(并且在未来的 Python 版本中可能会增加);最高版本是 sys.version_info[0:2]。“尽力而为”意味着不保证解析(或解析的成功)与在对应于 feature_version 的 Python 版本上运行时相同。

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

警告

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

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

警告

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

在 3.8 版本发生变更: 添加了 type_commentsmode='func_type'feature_version

在 3.13 版本发生变更: feature_version 的最低支持版本现在是 (3, 7)。添加了 optimize 参数。

ast.unparse(ast_obj)

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

警告

生成的代码字符串不一定等于生成 ast.AST 对象的原始代码(在没有任何编译器优化的情况下,例如常量元组/frozensets)。

警告

尝试反解析一个高度复杂的表达式将导致 RecursionError

在 3.9 版本中新增。

ast.literal_eval(node_or_string)

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

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

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

警告

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

根据格式错误的输入,它可能引发 ValueError, TypeError, SyntaxError, MemoryErrorRecursionError

在 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 的源代码片段。如果缺少某些位置信息(lineno, end_lineno, col_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)

如果可能,将源位置(lineno, col_offset, end_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, show_empty=False)

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

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

如果 show_empty 为 false(默认值),可选的空列表将从输出中省略。可选的 None 值总是被省略。

在 3.9 版更改: 增加了 indent 选项。

在 3.13 版更改: 增加了 show_empty 选项。

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

编译器旗标

以下旗标可以传递给 compile() 以改变程序编译的效果

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

启用对顶层 awaitasync forasync with 和异步推导式的支持。

在 3.8 版本加入。

ast.PyCF_ONLY_AST

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

ast.PyCF_OPTIMIZED_AST

返回的 AST 将根据 compile()ast.parse() 中的 optimize 参数进行优化。

在 3.13 版本加入。

ast.PyCF_TYPE_COMMENTS

启用对 PEP 484PEP 526 风格类型注释(# type: <type>, # type: ignore <stuff>)的支持。

在 3.8 版本加入。

ast.compare(a, b, /, *, compare_attributes=False)

递归地比较两个 AST。

compare_attributes 影响 AST 属性是否在比较中被考虑。如果 compare_attributesFalse(默认值),则属性被忽略。否则它们必须全部相等。这个选项对于检查 AST 是否在结构上相等,但在空格或类似细节上有所不同很有用。属性包括行号和列偏移。

在 3.14 版本加入。

命令行用法

在 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 中节点的缩进(空格数)。

--feature-version <version>

Python 版本,格式为 3.x(例如,3.10)。默认为解释器的当前版本。

在 3.14 版本加入。

-O <level>
--optimize <level>

解析器的优化级别。默认为不优化。

在 3.14 版本加入。

--show-empty

显示空列表和值为 None 的字段。默认为不显示空对象。

在 3.14 版本加入。

如果指定了 infile,其内容将被解析为 AST 并转储到标准输出。否则,内容从标准输入读取。

参见

Green Tree Snakes,一个外部文档资源,提供了有关使用 Python AST 的详细信息。

ASTTokens 会为 Python AST 添加注释,标明生成它们的标记和文本在源代码中的位置。这对于进行源代码转换的工具很有帮助。

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

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

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