ast — 抽象语法树 — Python 文档

来自菜鸟教程
Python/docs/3.10/library/ast
跳转至:导航、​搜索

ast — 抽象语法树

源代码: :source:`Lib/ast.py`



ast 模块帮助 Python 应用程序处理 Python 抽象语法语法树。 抽象语法本身可能会随着每个 Python 版本而改变; 该模块有助于以编程方式找出当前语法的样子。

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

抽象语法

抽象语法目前定义如下:

-- ASDL's 4 builtin types are:
-- identifier, int, string, constant

module Python
{
    mod = Module(stmt* body, type_ignore* type_ignores)
        | Interactive(stmt* body)
        | Expression(expr body)
        | FunctionType(expr* argtypes, expr returns)

    stmt = FunctionDef(identifier name, arguments args,
                       stmt* body, expr* decorator_list, expr? returns,
                       string? type_comment)
          | AsyncFunctionDef(identifier name, arguments args,
                             stmt* body, expr* decorator_list, expr? returns,
                             string? type_comment)

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

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

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

          | Match(expr subject, match_case* cases)

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

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

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

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

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

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

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

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

    expr_context = Load | Store | Del

    boolop = And | Or

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

    unaryop = Invert | Not | UAdd | USub

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

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

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

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

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

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

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

    withitem = (expr context_expr, expr? optional_vars)

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

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

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

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

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

    type_ignore = TypeIgnore(int lineno, string tag)
}

节点类

class ast.AST

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

为抽象语法中的每个左侧符号定义了一个类(例如,ast.stmtast.expr)。 此外,右侧为每个构造函数定义了一个类; 这些类继承自左侧树的类。 例如,ast.BinOp 继承自 ast.expr。 对于带有替代项(又名“总和”)的产生式规则,左侧的类是抽象的:只创建特定构造函数节点的实例。

_fields

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

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

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

lineno
col_offset
end_lineno
end_col_offset

ast.exprast.stmt 子类的实例具有 linenocol_offsetend_lineno 和 end_col_offset] 属性. linenoend_lineno 是源文本跨度的第一个和最后一个行号(1 索引,所以第一行是第 1 行)和 col_offset 和 [ X172X]end_col_offset 是生成节点的第一个和最后一个令牌的相应 UTF-8 字节偏移量。 记录 UTF-8 偏移量是因为解析器在内部使用 UTF-8。

请注意,编译器不需要结束位置,因此是可选的。 结束偏移量是最后一个符号之后的,例如可以使用source_line[node.col_offset : node.end_col_offset]得到一个单行表达式节点的源段。

ast.T 的构造函数解析其参数如下:

  • 如果有位置参数,则必须与T._fields中的项一样多; 它们将被分配为这些名称的属性。

  • 如果有关键字参数,它们会将同名的属性设置为给定的值。

例如,要创建和填充 ast.UnaryOp 节点,您可以使用

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

或者更紧凑

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

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


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


自 3.8 版起已弃用:旧类 ast.Numast.Strast.Bytesast.NameConstantast.Ellipsis 仍然可用,但它们将在未来的 Python 版本中删除。 同时,实例化它们将返回不同类的实例。


自 3.9 版起已弃用: 旧类 ast.Indexast.ExtSlice 仍然可用,但它们将在未来的 Python 版本中删除。 同时,实例化它们将返回不同类的实例。


笔记

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


文字

class ast.Constant(value)

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

>>> 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())],
                    keywords=[]),
                conversion=-1,
                format_spec=JoinedStr(
                    values=[
                        Constant(value='.3')]))]))
class ast.List(elts, ctx)
class ast.Tuple(elts, ctx)

列表或元组。 elts 保存代表元素的节点列表。 ctxStore 如果容器是分配目标(即 (x,y)=something) 和 Load 否则。

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

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

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

一本字典。 keysvalues 按匹配顺序分别保存表示键和值的节点列表(调用 dictionary.keys()dictionary.values() 时将返回什么)。

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

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


变量

class ast.Name(id, ctx)
一个变量名。 id 将名称保存为字符串,ctx 是以下类型之一。
class ast.Load
class ast.Store
class ast.Del

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

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

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

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

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

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

一元运算符令牌。 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)

布尔运算,“或”或“与”。 opvalues 是涉及的值。 具有相同操作符的连续操作,例如 a or b or c,被折叠为具有多个值的一个节点。

这不包括 not,它是一个 UnaryOp

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

class ast.Or

布尔运算符标记。
class ast.Compare(left, ops, comparators)

两个或多个值的比较。 left 是比较中的第一个值,ops 是运算符列表,comparators 是比较中第一个元素之后的值列表。

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

class ast.NotEq
class ast.Lt
class ast.LtE
class ast.Gt
class ast.GtE
class ast.Is
class ast.IsNot
class ast.In
class ast.NotIn

比较运算符标记。
class ast.Call(func, args, keywords, starargs, kwargs)

一个函数调用。 func 是函数,通常是 NameAttribute 对象。 论据:

  • args 保存按位置传递的参数列表。

  • keywords 保存了一个 keyword 对象列表,表示关键字传递的参数。

创建Call节点时,需要argskeywords,但可以是空列表。 starargskwargs 是可选的。

>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4))
Expression(
    body=Call(
        func=Name(id='func', ctx=Load()),
        args=[
            Name(id='a', ctx=Load()),
            Starred(
                value=Name(id='d', ctx=Load()),
                ctx=Load())],
        keywords=[
            keyword(
                arg='b',
                value=Name(id='c', ctx=Load())),
            keyword(
                value=Name(id='e', ctx=Load()))]))
class ast.keyword(arg, value)
函数调用或类定义的关键字参数。 arg 是参数名的原始字符串,value 是要传入的节点。
class ast.IfExp(test, body, orelse)

一个表达式,例如 a if b else c。 每个字段包含一个节点,因此在以下示例中,所有三个都是 Name 节点。

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

属性访问,例如 d.keysvalue 是一个节点,通常是一个 Nameattr 是给出属性名称的裸字符串,ctxLoadStoreDel如何作用于属性。

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

命名表达式。 该 AST 节点由赋值表达式运算符(也称为 walrus 运算符)生成。 与第一个参数可以是多个节点的 Assign 节点相反,在这种情况下,targetvalue 都必须是单个节点。

>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4))
Expression(
    body=NamedExpr(
        target=Name(id='x', ctx=Store()),
        value=Constant(value=4)))

下标

class ast.Subscript(value, slice, ctx)

下标,例如 l[1]value 是下标对象(通常是序列或映射)。 slice 是索引、切片或键。 它可以是 元组 并包含 切片ctxLoadStoreDel 根据下标执行的动作。

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

理解中的一个 for 子句。 target 是用于每个元素的引用 - 通常是 NameTuple 节点。 iter 是要迭代的对象。 ifs 是测试表达式列表:每个 for 子句可以有多个 ifs

is_async 表示理解是异步的(使用 async for 而不是 for)。 该值是一个整数(0 或 1)。

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

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

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


声明

class ast.Assign(targets, value, type_comment)

一个任务。 targets 是节点列表,value 是单个节点。

targets 中的多个节点表示为每个节点分配相同的值。 解包通过在 targets 中放入 TupleList 来表示。

type_comment

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

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

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

带有类型注释的赋值。 target 是单个节点,可以是 NameAttributeSubscriptannotation 是注释,例如 ConstantName 节点。 value 是单个可选节点。 simple 是一个布尔整数,对于 target 中的 Name 节点设置为 True,该节点没有出现在括号之间,因此是纯名称而不是表达式。

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

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

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

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

增强分配,例如 a += 1。 在以下示例中,targetxName 节点(具有 Store 上下文),op]Addvalue 是一个 常数 ,值为 1。

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

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

raise 语句。 exc 是要引发的异常对象,通常是 CallName,或 None 用于独立的 raisecauseraise x from yy的可选部分。

>>> print(ast.dump(ast.parse('raise x from y'), indent=4))
Module(
    body=[
        Raise(
            exc=Name(id='x', ctx=Load()),
            cause=Name(id='y', ctx=Load()))],
    type_ignores=[])
class ast.Assert(test, msg)

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

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

表示 del 语句。 targets 是节点列表,例如 NameAttributeSubscript 节点。

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

pass 语句。

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

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

进口

class ast.Import(names)

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

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

代表 from x import ymodule 是“来自”名称的原始字符串,没有任何前导点,或 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 节点。 bodyorelse 各持有一个节点列表。

elif 子句在 AST 中没有特殊表示,而是在前一个的 orelse 部分中作为额外的 If 节点出现。

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

for 循环。 target 保存循环分配给的变量,作为单个 NameTupleList 节点。 iter 保存要循环的项目,再次作为单个节点。 bodyorelse 包含要执行的节点列表。 如果循环正常结束,则执行 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

breakcontinue 语句。

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

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

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

单个 except 子句。 type 是它将匹配的异常类型,通常是 Name 节点(或 None 用于全面 except: 子句)。 name 是用于保存异常的名称的原始字符串,如果子句没有 as foo,则为 Nonebody 是节点列表。

>>> print(ast.dump(ast.parse("""\
... try:
...     a + 1
... except TypeError:
...     pass
... """), indent=4))
Module(
    body=[
        Try(
            body=[
                Expr(
                    value=BinOp(
                        left=Name(id='a', ctx=Load()),
                        op=Add(),
                        right=Constant(value=1)))],
            handlers=[
                ExceptHandler(
                    type=Name(id='TypeError', ctx=Load()),
                    body=[
                        Pass()])],
            orelse=[],
            finalbody=[])],
    type_ignores=[])
class ast.With(items, body, type_comment)
with 块。 items 是一个 withitem 节点的列表,代表上下文管理器,body 是上下文内的缩进块。
type_comment
type_comment 是一个可选字符串,带有类型注释作为注释。
class ast.withitem(context_expr, optional_vars)

with 块中的单个上下文管理器。 context_expr 是上下文管理器,通常是一个 Call 节点。 optional_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())],
                        keywords=[]))])],
    type_ignores=[])


模式匹配

class ast.Match(subject, cases)
match 语句。 subject 包含匹配的主题(与案例匹配的对象),cases 包含具有不同案例的 match_case 节点的迭代。
class ast.match_case(pattern, guard, body)

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

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

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

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

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

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

按标识进行比较的匹配文字模式。 value 是要与以下对象进行比较的单例:NoneTrueFalse。 如果匹配主题是给定的常量,则此模式成功。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

匹配“或模式”。 or-模式依次将其每个子模式与主题匹配,直到成功为止。 然后认为 or 模式成功。 如果没有一个子模式成功,则 or 模式失败。 patterns 属性包含将与主题匹配的匹配模式节点列表。

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


函数和类定义

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

一个函数定义。

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

  • args 是一个 arguments 节点。

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

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

  • returns 是返回注释。

type_comment

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

class ast.Lambda(args, body)

lambda 是可以在表达式中使用的最小函数定义。 与 FunctionDef 不同,body 持有单个节点。

>>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4))
Module(
    body=[
        Expr(
            value=Lambda(
                args=arguments(
                    posonlyargs=[],
                    args=[
                        arg(arg='x'),
                        arg(arg='y')],
                    kwonlyargs=[],
                    kw_defaults=[],
                    defaults=[]),
                body=Constant(value=Ellipsis)))],
    type_ignores=[])
class ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)
函数的参数。
  • posonlyargsargskwonlyargsarg 节点的列表。
  • varargkwarg为单arg节点,参考*args, **kwargs参数。
  • kw_defaults 是仅关键字参数的默认值列表。 如果一个是None,则需要相应的参数。
  • defaults 是可以按位置传递的参数的默认值列表。 如果默认值较少,则它们对应于最后 n 个参数。
class ast.arg(arg, annotation, type_comment)

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

type_comment

type_comment 是可选字符串,类型注解作为注释

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

return 语句。

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

yieldyield from 表达式。 因为这些是表达式,所以如果不使用发回的值,它们必须包含在 Expr 节点中。

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

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

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

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

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

一个类定义。

  • name 是类名的原始字符串

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

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

  • starargskwargs 都是一个节点,就像在函数调用中一样。 starargs 将被扩展以加入基类列表,kwargs 将被传递给元类。

  • body 是代表类定义中代码的节点列表。

  • decorator_list 是一个节点列表,如 FunctionDef

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


异步和等待

class ast.AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment)
async def 函数定义。 具有与 FunctionDef 相同的字段。
class ast.Await(value)
await 表达式。 value 就是它所等待的。 仅在 AsyncFunctionDef 的主体中有效。
>>> print(ast.dump(ast.parse("""\
... async def f():
...     await other_func()
... """), indent=4))
Module(
    body=[
        AsyncFunctionDef(
            name='f',
            args=arguments(
                posonlyargs=[],
                args=[],
                kwonlyargs=[],
                kw_defaults=[],
                defaults=[]),
            body=[
                Expr(
                    value=Await(
                        value=Call(
                            func=Name(id='other_func', ctx=Load()),
                            args=[],
                            keywords=[])))],
            decorator_list=[])],
    type_ignores=[])
class ast.AsyncFor(target, iter, body, orelse, type_comment)

class ast.AsyncWith(items, body, type_comment)

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

笔记

ast.parse()解析字符串时,算子节点(ast.operatorast.unaryopast.cmpopast.boolop的子类)和 ast.expr_context) 在返回的树上将是单例。 对一个的更改将反映在所有其他出现的相同值中(例如 ast.Add)。


ast 助手

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

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

将源解析为 AST 节点。 相当于 compile(source, filename, mode, ast.PyCF_ONLY_AST)

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

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

此外,将 feature_version 设置为元组 (major, minor) 将尝试使用该 Python 版本的语法进行解析。 当前 major 必须等于 3。 例如,设置 feature_version=(3, 4) 将允许使用 asyncawait 作为变量名。 支持的最低版本是(3, 4); 最高的是sys.version_info[0:2]

如果源包含空字符 ('0'),则引发 ValueError

警告

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

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

警告

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

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

ast.unparse(ast_obj)

解解析 ast.AST 对象并生成一个字符串,其中的代码将生成等效的 ast.AST 对象,如果用 ast.parse() 解析回来。

警告

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

警告

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

3.9 版中的新功能。

ast.literal_eval(node_or_string)

安全地计算包含 Python 文字或容器显示的表达式节点或字符串。 提供的字符串或节点只能包含以下 Python 文字结构:字符串、字节、数字、元组、列表、字典、集合、布尔值、NoneEllipsis

这可用于安全地评估包含来自不受信任来源的 Python 值的字符串,而无需自己解析这些值。 它不能评估任意复杂的表达式,例如涉及运算符或索引。

警告

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

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

3.2 版更改: 现在允许字节和设置文字。

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

在 3.10 版更改:对于字符串输入,现在去除前导空格和制表符。

ast.get_docstring(node, clean=True)

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

3.5 版更改:现在支持 AsyncFunctionDef

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

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

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

3.8 版中的新功能。

ast.fix_missing_locations(node)
当您使用 compile() 编译节点树时,编译器期望每个支持它们的节点具有 linenocol_offset 属性。 填充生成的节点相当繁琐,因此该助手通过将这些属性设置为父节点的值,在尚未设置的地方递归添加这些属性。 它从 节点 开始递归地工作。
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._fields 中的每个字段生成一个 (fieldname, value) 元组。
ast.iter_child_nodes(node)
生成 node 的所有直接子节点,即作为节点的所有字段和作为节点列表的所有字段项。
ast.walk(node)
递归生成树中从 node 开始的所有后代节点(包括 node 本身),没有指定的顺序。 如果您只想就地修改节点而不关心上下文,这将非常有用。
class ast.NodeVisitor

一个节点访问者基类,它遍历抽象语法树并为找到的每个节点调用一个访问者函数。 此函数可能会返回一个值,该值由 visit() 方法转发。

此类旨在被子类化,子类添加访问者方法。

visit(node)

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

generic_visit(node)

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

请注意,除非访问者调用 generic_visit() 或自己访问它们,否则不会访问具有自定义访问者方法的节点的子节点。

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

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

class ast.NodeTransformer

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

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

这是一个示例转换器,它将所有出现的名称查找 (foo) 重写为 data['foo']

class RewriteName(NodeTransformer):

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

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

对于作为语句集合的一部分(适用于所有语句节点)的节点,访问者还可以返回节点列表而不仅仅是单个节点。

如果 NodeTransformer 引入新节点(不属于原始树的一部分)而不提供位置信息(例如 lineno),则应调用 fix_missing_locations()重新计算位置信息的新子树:

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

通常你像这样使用变压器:

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

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

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

3.9 版更改: 添加 缩进 选项。


编译器标志

以下标志可以传递给 compile() 以更改对程序编译的影响:

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

启用对顶级 awaitasync forasync with 和异步理解的支持。

3.8 版中的新功能。

ast.PyCF_ONLY_AST
生成并返回抽象语法树,而不是返回已编译的代码对象。
ast.PyCF_TYPE_COMMENTS

启用对 PEP 484PEP 526 样式类型注释的支持 (# type: <type>, # type: ignore <stuff> .

3.8 版中的新功能。


命令行使用

3.9 版中的新功能。


ast 模块可以从命令行作为脚本执行。 它很简单:

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

接受以下选项:

-h, --help
显示帮助信息并退出。
-m <mode>

--mode <mode>

指定必须编译的代码类型,例如 parse() 中的 mode 参数。
--no-type-comments
不要解析类型注释。
-a, --include-attributes
包括行号和列偏移等属性。
-i <indent>

--indent <indent>

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

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

也可以看看

Green Tree Snakes 是一个外部文档资源,其中包含有关使用 Python AST 的详细信息。

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

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

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

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