ast —- 抽象语法树

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)
               | ParamSpec(identifier name)
               | TypeVarTuple(identifier name)
               attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
}

节点类

class ast.AST

这是所有 AST 节点类的基类。实际上,这些节点类来源于 Parser/Python.asdl 文件,文件内容已被完整展示 如上。它们在 C 模块 _ast 中定义,并在这个 ast 模块中被“再导出”给用户。

抽象文法中的每个等号左边的符号(比方说, ast.stmt 或者 ast.expr)定义了一个类。另外,在等号右边,对每一个构造器也定义了一个类;这些类继承自等号左边的类。比如,ast.BinOp 继承自 ast.expr。对于多分支产生式(也就是含有“ | ”的产生式),左边的类是抽象的;只有具体构造器类的实例能够被 compile 函数构造。

  • _fields

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

每个具体类的实例为自己的每个子节点都准备了一个属性来引用该子节点,属性的类型就是文法中所定义的。比如,ast.BinOp 的实例有个属性 left,类型是 ast.expr。

如果这些属性在文法中标记为可选(用问号标记),对应值可能会是 None。如果这些属性可有零或多个值(用星号标记),对应值会用Python的列表来表示。在用 compile() 将AST编译为可执行代码时,所有的属性必须已经被赋值为有效的值。

  • lineno

col_offset

end_lineno

end_col_offset

ast.expr 和 ast.stmt 的子类的实例的属性包括 lineno、col_offset、end_lineno 和 end_col_offset。lineno 和 end_lineno 是源码中属于该节点的部分从哪一行开始,到哪一行结束(数字 1 指第一行,以此类推);col_offset 和 end_col_offset 是第一个和最后一个属于该节点的 token 的 UTF-8 字节偏移量。记录 UTF-8 偏移量的原因是解析器内部使用 UTF-8。

注意编译器不需要结束位置,所以结束位置是可选的。结束偏移在最后一个符号 之后 ,例如你可以通过 source_line[node.col_offset : node.end_col_offset] 获得一个单行表达式节点的源码片段。

ast.T 类的构造器像下面这样解析它的参数:

  • 如果只用位置参数,参数的数量必须和 T._fields 中的项一样多;它们会按顺序赋值到这些属性上。

  • 如果有关键字参数,它们会为与其关键字同名的属性赋值。

比方说,要创建和填充节点 ast.UnaryOp,你得用

node = ast.UnaryOp()
node.op = ast.USub()
node.operand = ast.Constant()
node.operand.value = 5
node.operand.lineno = 0
node.operand.col_offset = 0
node.lineno = 0
node.col_offset = 0

或者更紧凑点

node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
                   lineno=0, col_offset=0)

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

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

3.8 版后已移除: 旧的类 ast.Num、ast.Str、 ast.Bytes、ast.NameConstant 和 ast.Ellipsis 仍然有效,但是它们会在未来的 Python 版本中被移除。同时,实例化它们会返回一个不同类的实例。

3.9 版后已移除: 旧的类 ast.Index 和 ast.ExtSlice 仍然有效,但是它们会在未来的 Python 版本中被移除。同时,实例化它们会返回一个不同类的实例。

备注

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

根节点

class ast.Module(body , type_ignores)

一个 Python 模块,用于 文件输入。 由 ast.parse() 以默认 "exec" mode 生成的节点类型。

body 是由该模块的 语句 组成的 list。

type_ignores 是由该模块的类型忽略注释组成的 list;请参阅 ast.parse() 了解更多细节。

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

class ast.Expression(body)

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

body 为单独节点,是 表达式类型 中的某一个。

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

class ast.Interactive(body)

单个 交互式输入,就像在 交互模式 中一样。 当 mode 为 "single" 时由 ast.parse() 所生成的节点类型。

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)

函数的旧风格类型注释表示形式,因为 Python 3.5 之前的版本不支持 PEP 484 标注。 当 mode is "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 对象。它可以代表简单的数字,字符串或者 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 节点,或者如果未指定格式则为 None。 conversion 和 format_spec 可以被同时设置。

class ast.JoinedStr(values)

一个 f-字符串,由一系列 FormattedValue 和 Constant 节点组成。

>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4))
Expression(
    body=JoinedStr(
        values=[
            Constant(value='sin('),
            FormattedValue(
                value=Name(id='a', ctx=Load()),
                conversion=-1),
            Constant(value=') is '),
            FormattedValue(
                value=Call(
                    func=Name(id='sin', ctx=Load()),
                    args=[
                        Name(id='a', ctx=Load())],
                    keywords=[]),
                conversion=-1,
                format_spec=JoinedStr(
                    values=[
                        Constant(value='.3')]))]))

class ast.List(elts , ctx)

class ast.Tuple(elts , ctx)

一个列表或元组。 elts 保存一个代表元素的节点的列表。 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)

一个字典。 keys 和 values 保存分别代表键和值的节点的列表,按照匹配的顺序(即当调用 dictionary.keys() 和 dictionary.values() 时将返回的结果)。

当使用字典字面值进行字典解包操作时要扩展的表达式放入 values 列表,并将 None 放入 keys 的对应位置。

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

变量

class ast.Name(id , ctx)

一个变量名。 id 将名称保存为字符串,而 ctx 为下列类型之一。

class ast.Load

class ast.Store

class ast.Del

变量引用可被用来载入一个变量的值,为其赋一个新值,或是将其删除。 变量引用会给出一个上下文来区分这几种情况。

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

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

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

class ast.Starred(value , ctx)

一个 *var 变量引用。 value 保存变量,通常为一个 Name 节点。 此类型必须在构建 Call 节点并传入 *args 时被使用。

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

表达式

class ast.Expr(value)

当一个表达式,例如函数调用,本身作为一个语句出现并且其返回值未被使用或存储时,它会被包装在此容器中。 value 保存本节中的其他节点之一,一个 Constant, 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())))],
    type_ignores=[])

class ast.UnaryOp(op , operand)

一个单目运算。 op 是运算符,而 operand 是任意表达式节点。

class ast.UAdd

class ast.USub

class ast.Not

class ast.Invert

单目运算符对应的形符。 Not 是 not 关键字,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 是运算符,而 left 和 right 是任意表达式节点。

>>> 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’。 op 是 Or 或者 And。 values 是参与运算的值。 具有相同运算符的连续运算,如 a or b or c,会被折叠为具有多个值的单个节点。

这不包括 not,它属于 UnaryOp。

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

class ast.And

class ast.Or

布尔运算符对应的形符。

class ast.Compare(left , ops , comparators)

两个或更多值之间的比较运算。 left 是参加比较的第一个值,ops 是由运算符组成的列表,而 comparators 是由参加比较的第一个元素之后的值组成的列表。

>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4))
Expression(
    body=Compare(
        left=Constant(value=1),
        ops=[
            LtE(),
            Lt()],
        comparators=[
            Name(id='a', ctx=Load()),
            Constant(value=10)]))

class ast.Eq

class ast.NotEq

class ast.Lt

class ast.LtE

class ast.Gt

class ast.GtE

class ast.Is

class ast.IsNot

class ast.In

class ast.NotIn

比较运算符对应的形符。

class ast.Call(func , args , keywords)

一个函数调用。 func 是函数,它通常是一个 Name 或 Attribute 对象。 对于其参数:

  • args 保存由按位置传入的参数组成的列表。

  • keywords 保存了一个代表以关键字传入的参数的 keyword 对象的列表。

当创建 Call 节点时,需要有 args 和 keywords,但它们可以为空列表。

>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4))
Expression(
    body=Call(
        func=Name(id='func', ctx=Load()),
        args=[
            Name(id='a', ctx=Load()),
            Starred(
                value=Name(id='d', ctx=Load()),
                ctx=Load())],
        keywords=[
            keyword(
                arg='b',
                value=Name(id='c', ctx=Load())),
            keyword(
                value=Name(id='e', ctx=Load()))]))

class ast.keyword(arg , value)

传给函数调用或类定义的关键字参数。 arg 是形参名称对应的原始字符串,value 是要传入的节点。

class ast.IfExp(test , body , orelse)

一个表达式例如 a if b else c。 每个字段保存一个单独节点,因而在下面的示例中,三个节点均为 Name 节点。

>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4))
Expression(
    body=IfExp(
        test=Name(id='b', ctx=Load()),
        body=Name(id='a', ctx=Load()),
        orelse=Name(id='c', ctx=Load())))

class ast.Attribute(value , attr , ctx)

属性访问,例如 d.keys。 value 是一个节点,通常为 Name。 attr 是一个给出属性名称的纯字符串,而 ctx 根据属性操作的方式可以为 Load, Store 或 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 节点不同,在此情况下 target 和 value 都必须为单独节点。

>>> 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 是索引号、切片或键。 它可以是一个包含 Slice 的 Tuple。 ctx 根据抽取所执行的操作可以为 Load, Store 或 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:upper 或 lower:upper:step)。 只能在 Subscript 的 slice 字段内部出现,可以是直接切片对象或是作为 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 (或 key 和 value) 是一个代表将针对每个条目被求值的部分的单独节点。

generators 是一个由 comprehension 节点组成的列表。

>>> print(ast.dump(ast.parse('[x for x in numbers]', mode='eval'), indent=4))
Expression(
    body=ListComp(
        elt=Name(id='x', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                ifs=[],
                is_async=0)]))
>>> print(ast.dump(ast.parse('{x: x**2 for x in numbers}', mode='eval'), indent=4))
Expression(
    body=DictComp(
        key=Name(id='x', ctx=Load()),
        value=BinOp(
            left=Name(id='x', ctx=Load()),
            op=Pow(),
            right=Constant(value=2)),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                ifs=[],
                is_async=0)]))
>>> print(ast.dump(ast.parse('{x for x in numbers}', mode='eval'), indent=4))
Expression(
    body=SetComp(
        elt=Name(id='x', ctx=Load()),
        generators=[
            comprehension(
                target=Name(id='x', ctx=Store()),
                iter=Name(id='numbers', ctx=Load()),
                ifs=[],
                is_async=0)]))

class ast.comprehension(target , iter , ifs , is_async)

推导式中的一个 for 子句。 target 是针对每个元素使用的引用 —— 通常为一个 Name 或 Tuple 节点。 iter 是要执行迭代的对象。 ifs 是一个由测试表达式组成的列表:每个 for 子句都可以拥有多个 ifs。

is_async 表明推导式是异步的 (使用 async for 而不是 for)。 它的值是一个整数 (0 或 1)。

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

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

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

语句

class ast.Assign(targets , value , type_comment)

一次赋值。 targets 是一个由节点组成的列表,而 value 是一个单独节点。

targets 中有多个节点表示将同一个值赋给多个目标。 解包操作是通过在 targets 中放入一个 Tuple 或 List 来表示的。

  • type_comment

type_comment 是带有以注释表示的类型标注的可选的字符串。

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

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

class ast.AnnAssign(target , annotation , value , simple)

一次带有类型标注的赋值。 target 为单独节点并可以是 Name, Attribute 或 Subscript 之一。 annotation 为标注,例如一个 Constant 或 Name 节点。 value 为可选的单独节点。 simple 为一个布尔整数,其值对于 target 中不出现在括号之内因而是纯名称而非表达式的 Name 节点将为 True。

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

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

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

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

class ast.AugAssign(target , op , value)

增强赋值,如 a += 1。 在下面的例子中,target 是一个针对 x (带有 Store 上下文) 的 Name 节点,op 为 Add,而 value 是一个值为 1 的 Constant。

target 属性不可以是 Tuple 或 List 类,这与 Assign 的目标不同。

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

class ast.Raise(exc , cause)

一条 raise 语句。 exc 是要引发的异常,对于一个单独的 raise 通常为 Call 或 Name,或者为 None。 cause 是针对 raise 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()))],
    type_ignores=[])

class ast.Assert(test , msg)

一条断言。 test 保存条件,例如为一个 Compare 节点。 msg 保存失败消息。

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

class ast.Delete(targets)

代表一条 del 语句。 targets 是一个由节点组成的列表,例如 Name, Attribute 或 Subscript 节点。

>>> print(ast.dump(ast.parse('del x,y,z'), indent=4))
Module(
    body=[
        Delete(
            targets=[
                Name(id='x', ctx=Del()),
                Name(id='y', ctx=Del()),
                Name(id='z', ctx=Del())])],
    type_ignores=[])

class ast.Pass

一条 pass 语句。

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

class ast.TypeAlias(name , type_params , value)

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

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

3.12 新版功能.

其他仅在函数或循环内部可用的语句将在其他小节中描述。

导入

class ast.Import(names)

一条导入语句。 names 是一个由 alias 节点组成的列表。

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

class ast.ImportFrom(module , names , level)

代表 from x import y。 module 是一个 ‘from’ 名称的原始字符串,不带任何前导点号,或者为 None 表示 from . import foo 这样的语句。 level 是一个保存相对导入层级的整数(0 表示绝对导入)。

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

class ast.alias(name , asname)

两个形参均为名称的原始字符串。 如果要使用常规名称则 asname 可以为 None。

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

控制流

备注

可选的子句如 else 如果不存在则会被存储为一个空列表。

class ast.If(test , body , orelse)

一条 if 语句。 test 保存一个单独节点,如一个 Compare 节点。 body 和 orelse 各自保存一个节点列表。

elif 子句在 AST 中没有特别的表示形式,而是作为上文介绍的 orelse 部分之内的一个额外 If 节点出现。

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

class ast.For(target , iter , body , orelse , type_comment)

一个 for 循环。 target 保存循环赋值的变量,是一个单独的 Name, Tuple, List, Attribute 或 Subscript 节点。 iter 保存要被循环的条目,同样也是一个单独节点。 body 和 orelse 包含要执行的节点列表。 orelse 中的语句会在循环正常结束时被执行,而不是通过 break 语句执行。

  • type_comment

type_comment 是带有以注释表示的类型标注的可选的字符串。

>>> print(ast.dump(ast.parse("""
... for x in y:
...     ...
... else:
...     ...
... """), indent=4))
Module(
    body=[
        For(
            target=Name(id='x', ctx=Store()),
            iter=Name(id='y', ctx=Load()),
            body=[
                Expr(
                    value=Constant(value=Ellipsis))],
            orelse=[
                Expr(
                    value=Constant(value=Ellipsis))])],
    type_ignores=[])

class ast.While(test , body , orelse)

一个 while 循环。 test 保存条件,如一个 Compare 节点。

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

class ast.Break

class ast.Continue

break 和 continue 语句。

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

class ast.Try(body , handlers , orelse , finalbody)

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

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

class ast.TryStar(body , handlers , orelse , finalbody)

try 代码块后带有 except* 子句。 包含的属性与 Try 的相同但 ExceptHandler 节点在 handlers 中会被解读为 except* 而不是 except 代码块。

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

3.11 新版功能.

class ast.ExceptHandler(type , name , body)

一个单独的 except 子句。 type 是它将匹配的异常,通常为一个 Name 节点(或 None 表示捕获全部的 except: 子句)。 name 是一个用于存放异常的别名的原始字符串,或者如果子句没有 as foo 则为 None。 body 为一个节点列表。

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

class ast.With(items , body , type_comment)

一个 with 代码块。 items 是一个代表上下文管理器的 withitem 节点列表,而 body 是该上下文中的缩进代码块。

  • type_comment

type_comment 是带有以注释表示的类型标注的可选的字符串。

class ast.withitem(context_expr , optional_vars)

一个 with 代码块中单独的上下文管理器。 context_expr 为上下文管理器,通常为一个 Call 节点。 optional_vars 为一个针对 as foo 部分的 Name, Tuple 或 List,或者如果未使用别名则为 None。

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

(本文超出站点单文档体积上限,已按小节截断)