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)
         | 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, 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 开始索引,因此第一行是行 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.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" *模式* 中的 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() 生成的节点类型。

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 字符串中单个格式化字段的节点。如果字符串包含单个格式化字段并且没有其他内容,则该节点可以被隔离,否则它将出现在 JoinedStr 中。

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

  • conversion 是一个整数

    • -1: 无格式化

    • 115: !s 字符串格式化

    • 114: !r repr 格式化

    • 97: !a ascii 格式化

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

class ast.JoinedStr(values)

一个 f 字符串,由一系列 FormattedValueConstant 节点组成。

>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4))
Expression(
    body=JoinedStr(
        values=[
            Constant(value='sin('),
            FormattedValue(
                value=Name(id='a', ctx=Load()),
                conversion=-1),
            Constant(value=') is '),
            FormattedValue(
                value=Call(
                    func=Name(id='sin', ctx=Load()),
                    args=[
                        Name(id='a', ctx=Load())]),
                conversion=-1,
                format_spec=JoinedStr(
                    values=[
                        Constant(value='.3')]))]))
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 保存本节中的其他节点之一,一个 Constant、一个 Name、一个 Lambda、一个 Yield 或一个 YieldFrom 节点。

>>> print(ast.dump(ast.parse('-a'), indent=4))
Module(
    body=[
        Expr(
            value=UnaryOp(
                op=USub(),
                operand=Name(id='a', ctx=Load())))])
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 是一个给出属性名称的裸字符串,并且 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)是表示将为每个项目评估的部分的单个节点。

generatorscomprehension 节点的列表。

>>> 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。在以下示例中,targetxName 节点(带有 Store 上下文),opAddvalue 是值为 1 的 Constant

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

>>> print(ast.dump(ast.parse('x += 2'), indent=4))
Module(
    body=[
        AugAssign(
            target=Name(id='x', ctx=Store()),
            op=Add(),
            value=Constant(value=2))])
class ast.Raise(exc, cause)

一个 raise 语句。exc 是要引发的异常对象,通常是 CallName,或者对于独立的 raise 来说是 Nonecauseraise x from y 中可选的 y 部分。

>>> print(ast.dump(ast.parse('raise x from y'), indent=4))
Module(
    body=[
        Raise(
            exc=Name(id='x', ctx=Load()),
            cause=Name(id='y', ctx=Load()))])
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)

一个导入语句。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')])])
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 中没有特殊的表示形式,而是作为前一个 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 保存循环赋值的变量,作为单个 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))])])
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_varsNameTupleList,用于表示 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())]))])])

模式匹配

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 属性包含一个表达式,如果模式与主题匹配,则会对其进行求值。

如果模式匹配且计算 guard 表达式的结果为 true,则 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 是一个可选的名称,可以指定用于捕获剩余的映射元素。 允许的键表达式受匹配语句文档中描述的限制。

如果主题是一个映射,所有计算出的键表达式都存在于该映射中,并且每个键对应的值与对应的子模式匹配,则此模式成功。如果 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 的属性,以便将模式节点与正在匹配的实例进行匹配。如匹配语句文档中所述,一些内置类型也以这种方式进行匹配。

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

一个匹配“或-模式”。或-模式依次将其每个子模式与主题进行匹配,直到一个成功。然后,或-模式被视为成功。如果没有一个子模式成功,则或-模式失败。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.TypeVar(name, bound, default_value)

一个 typing.TypeVarname 是类型变量的名称。 bound 是边界或约束(如果有)。如果 boundTuple,则表示约束;否则表示边界。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)

函数的参数。

  • 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(
                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.operatorast.unaryopast.cmpopast.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),其中 FLAGS_VALUEoptimize <= 0 时为 ast.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 版本上运行时相同。

如果源代码包含空字符(\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 对象的原始代码(没有任何编译器优化,例如常量元组/冻结集合)。

警告

尝试解析高度复杂的表达式会导致 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)

获取生成 *node* 的 *source* 的源代码片段。如果缺少一些位置信息(linenoend_linenocol_offsetend_col_offset),则返回 None

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

在 3.8 版本中添加。

ast.fix_missing_locations(node)

当您使用 compile() 编译节点树时,编译器期望每个支持它们的节点都有 linenocol_offset 属性。对于生成的节点,填充这些属性相当繁琐,因此此辅助函数通过将它们设置为父节点的值,以递归方式为尚未设置这些属性的节点添加这些属性。它从 *node* 开始递归工作。

ast.increment_lineno(node, n=1)

将从 *node* 开始的树中每个节点的行号和结束行号递增 *n*。 这对于将“代码移动”到文件中的不同位置很有用。

ast.copy_location(new_node, old_node)

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

ast.iter_fields(node)

为 *node* 中存在的每个 node._fields 中的字段生成一个 (字段名, 值) 的元组。

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_emptyFalse(默认值),则空列表和为 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 版本中添加。

命令行用法

在 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) 应用程序和 linters 很有用。

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