ast --- 抽象語法樹 (Abstract Syntax Trees)

原始碼:Lib/ast.py


ast 模組可以幫助 Python 應用程式處理 Python 抽象語法文法 (abstract syntax grammar) 樹狀資料結構。抽象語法本身可能會隨著每個 Python 版本發布而改變;此模組有助於以程式化的方式來得知當前文法的面貌。

要生成抽象語法樹,可以透過將 ast.PyCF_ONLY_AST 作為旗標傳遞給內建函式 compile() 或使用此模組所提供的 parse() 輔助函式。結果將會是一個物件的樹,其類別都繼承自 ast.AST。可以使用內建的 compile() 函式將抽象語法樹編譯成 Python 程式碼物件。

抽象文法 (Abstract Grammar)

抽象文法目前定義如下:

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

節點 (Node) 類別

class ast.AST

這是所有 AST 節點類別的基礎。實際的節點類別是衍生自 Parser/Python.asdl 檔案,該檔案在上方 重現。它們被定義於 _ast 的 C 模組中,並於 ast 中重新匯出。

抽象文法中為每個左側符號定義了一個類別(例如 ast.stmtast.expr)。此外,也為每個右側的建構函式 (constructor) 定義了一個類別;這些類別繼承自左側樹的類別。例如,ast.BinOp 繼承自 ast.expr。對於具有替代方案(即為「和 (sums)」)的生產規則,左側類別是抽象的:僅有特定建構函式節點的實例會被建立。

_fields

每個具體類別都有一個屬性 _fields,它會給出所有子節點的名稱。

具體類別的每個實例對於每個子節點都有一個屬性,其型別如文法中所定義。例如,ast.BinOp 實例具有型別為 ast.expr 的屬性 left

如果這些屬性在文法中被標記為可選(使用問號),則該值可能為 None。如果屬性可以有零個或多個值(用星號標記),則這些值將表示為 Python 串列。使用 compile() 編譯 AST 時,所有可能的屬性都必須存在並且具有有效值。

lineno
col_offset
end_lineno
end_col_offset

ast.exprast.stmt 子類別的實例具有 linenocol_offsetend_linenoend_col_offset 屬性。linenoend_lineno 是原始文本跨度 (source text span) 的第一個和最後一個列號(1-indexed,因此第一列號是 1)以及 col_offsetend_col_offset 是生成節點的第一個和最後一個標記對應的 UTF-8 位元組偏移量。會記錄 UTF-8 偏移量是因為剖析器 (parser) 內部使用 UTF-8。

請注意,編譯器並不需要結束位置,因此其為可選的。結束偏移量在最後一個符號之後,例如可以使用 source_line[node.col_offset : node.end_col_offset] 來獲取單列運算式節點 (expression node) 的原始片段。

ast.T 類別的建構函式按以下方式剖析其引數:

  • 如果有位置引數,則必須與 T._fields 中的項目一樣多;它們將被賦値為這些名稱的屬性。

  • 如果有關鍵字引數,它們會將相同名稱的屬性設定為給定值。

例如,要建立並填充 (populate) 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 版的變更: 以它們的值表示簡單索引,擴充切片 (slice) 則以元組 (tuple) 表示。

在 3.8 版之後被棄用: 舊的類別 ast.Numast.Strast.Bytesast.NameConstantast.Ellipsis 仍然可用,但它們將在未來的 Python 釋出版本中移除。與此同時,實例化它們將回傳不同類別的實例。

在 3.9 版之後被棄用: 舊的類別 ast.Indexast.ExtSlice 仍然可用,但它們將在未來的 Python 版本中刪除。同時,實例化它們會回傳不同類別的實例。

備註

這裡顯示的特定節點類別的描述最初是從出色的 Green Tree Snakes 專案和所有貢獻者那裡改編而來的。

根節點

class ast.Module(body, type_ignores)

一個 Python 模組,與檔案輸入 一樣。由 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陳述式節點 (statement nodes)list

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

函式的舊式型別註解的表示法,因為 3.5 之前的 Python 版本不支援 PEP 484 註釋。當 mode"func_type" 時節點型別由 ast.parse() 生成。

這種型別的註解看起來像這樣:

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

argtypes運算式節點list

returns 是單個運算式節點

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

在 3.8 版新加入.

文本 (Literals)

class ast.Constant(value)

一個常數值。Constant 文本的 value 屬性包含它所代表的 Python 物件。表示的值可以是簡單型別,例如數字、字串或 None,但如果它們的所有元素都是常數,也可以是不可變的 (immutable) 容器型別(元組和凍結集合 (frozensets))。

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

表示 f 字串 (f-string) 中的單個格式化欄位的節點。如果字串包含單個格式欄位並且沒有其他內容,則可以隔離 (isolate) 該節點,否則它將出現在 JoinedStr 中。

  • value 為任何運算式節點(例如文字、變數或函式呼叫)。

  • conversion 是一個整數:

    • -1: 無格式化

    • 115: !s 字串格式化

    • 114:!r 重複格式化化

    • 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 保存表示元素的節點串列。如果容器是賦值目標(即 (x,y)=something ),則 ctxStore,否則是 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)

一個字典 (dictionary)。keysvalues 分別按匹配順序保存表示鍵和值的節點串列(為呼叫 dictionary.keys()dictionary.values() 時將回傳的內容)。

當使用字典文本進行字典解包 (unpack) 時,要擴充的運算式位於 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

變數參照可用於載入變數的值、為其分配新值或刪除它。變數參照被賦予情境 (context) 來區分這些情況。

>>> 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 保存此區段 (section) 中的一個其他節點:ConstantNameLambdaYieldYieldFrom

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

一元運算 (unary operation)。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)

二元運算 (binary operation)(如加法或除法)。 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

二元運算子 token。

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

布林運算子 token。

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

比較運算子 token。

class ast.Call(func, args, keywords)

一個函式呼叫。func 是該函式,通常是一個 NameAttribute 物件。而在引數中:

  • args 保存按位置傳遞的引數串列。

  • keywords 保存一個 keyword 物件串列,表示透過關鍵字傳遞的引數。

建立 Call 節點時會需要 argskeywords,但它們可以是空串列。

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

函式呼叫或類別定義的關鍵字引數。arg 是參數名稱的原始字串,value 是要傳入的節點。

class ast.IfExp(test, body, orelse)

像是 a if b else c 之類的運算式。每個欄位都保存一個節點,因此在以下範例中,所有三個都是 Name 節點。

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

屬性的存取,例如 d.keysvalue 是一個節點,通常是一個 Nameattr 是一個屬性名稱的字串,ctx 根據屬性的作用方式可能是 LoadStoreDel

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

一個附名運算式 (named expression)。該 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 版新加入.

下標 (Subscripting)

class ast.Subscript(value, slice, ctx)

一個下標,例如 l[1]value 是下標物件(通常是序列或對映)。slice 是索引、切片或鍵。它可以是一個 Tuple 並包含一個 Slice。根據下標執行的操作不同,ctx 可以是 LoadStoreDel

>>> 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)。只能直接或者或者作為 Tuple 的元素出現在 Subscriptslice 欄位內。

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

綜合運算式 (comprehensions)

class ast.ListComp(elt, generators)
class ast.SetComp(elt, generators)
class ast.GeneratorExp(elt, generators)
class ast.DictComp(key, value, generators)

串列和集合綜合運算、生成器運算式和字典綜合運算。elt(或 keyvalue)是單個節點,表示各個項目會被求值 (evaluate) 的部分。

generators 是一個 comprehension 節點的串列。

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

綜合運算中的一個 for 子句。target 是用於每個元素的參照 - 通常是 NameTuple 節點。iter 是要疊代的物件。ifs 是測試運算式的串列:每個 for 子句可以有多個 ifs

is_async 表示綜合運算式是非同步的(使用 async for 而不是 for )。該值為整數(0 或 1)。

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

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

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

陳述式

class ast.Assign(targets, value, type_comment)

一個賦值。targets 是節點串列,value 是單個節點。

targets 中的多個節點表示為每個節點分配相同的值。解包是透過在 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)

增加賦值 (augmented assignment),例如 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))],
    type_ignores=[])
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()))],
    type_ignores=[])
class ast.Assert(test, msg)

一個斷言 (assertion)。test 保存條件,例如 Compare 節點。msg 保存失敗訊息。

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

代表一個 del 陳述式。targets 是節點串列,例如 NameAttributeSubscript 節點。

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

一個 pass 陳述式。

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

透過 type 陳述式建立的型別別名 (type alias)name 是別名的名稱、type_params型別參數 (type parameter) 的串列、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 版新加入.

其他僅適用於函式或迴圈內部的陳述式將在其他部分中描述。

引入 (imports)

class ast.Import(names)

一個 import 陳述式。namesalias 節點的串列。

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

代表 from x import ymodule 是 'from' 名稱的原始字串,前面沒有任何的點 (dot),或者對於諸如 from . import foo 之類的陳述式則為 Nonelevel 是一個整數,保存相對引入的級別(0 表示絕對引入)。

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

這兩個參數都是名稱的原始字串。如果要使用常規名稱,asname 可以為 None

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

流程控制

備註

諸如 else 之類的可選子句如果不存在,則將被儲存為空串列。

class ast.If(test, body, orelse)

一個 if 陳述式。test 保存單個節點,例如 Compare 節點。bodyorelse 各自保存一個節點串列。

elif 子句在 AST 中沒有特殊表示,而是在前一個子句的 orelse 部分中作為額外的 If 節點出現。

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

一個 for 迴圈。 target 保存迴圈賦予的變數,為單個 NameTupleListAttributeSubscript 節點。iter 保存要迴圈跑過的項目,也為單個節點。bodyorelse 包含要執行的節點串列。如果迴圈正常完成,則執行 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 區塊。除 handlersExceptHandler 節點的串列外,其他所有屬性都是要執行之節點的串列。

>>> 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 相同,但是 handlers 中的 ExceptHandler 節點被直譯 (interpret) 為 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 ,則為 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_varsas foo 部分的 NameTupleList,或者如果不使用則為 None

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

模式匹配 (pattern matching)

class ast.Match(subject, cases)

一個 match 陳述式。subject 保存匹配的主題(與案例匹配的物件),cases 包含具有不同案例的 match_case 節點的可疊代物件。

在 3.10 版新加入.

class ast.match_case(pattern, guard, body)

match 陳述式中的單個案例模式。pattern 包含主題將與之匹配的匹配模式。請注意,為模式生成的 AST 節點與為運算式生成的節點不同,即使它們共享相同的語法。

guard 屬性包含一個運算式,如果模式與主題匹配,則將對該運算式求值。

body 包含一個節點串列,如果模式匹配並且為防護運算式 (guard expression) 的求值 (evaluate) 結果為真,則會執行該節點串列。

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

在 3.10 版新加入.

class ast.MatchValue(value)

以相等性進行比較的匹配文本或值的模式。value 是一個運算式節點。允許值節點受到匹配陳述式文件中所述的限制。如果匹配主題等於求出值,則此模式成功。

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

在 3.10 版新加入.

class ast.MatchSingleton(value)

按識別性 (identity) 進行比較的匹配文本模式。value 是要與 NoneTrueFalse 進行比較的單例 (singleton)。如果匹配主題是給定的常數,則此模式成功。

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

在 3.10 版新加入.

class ast.MatchSequence(patterns)

匹配序列模式。如果主題是一個序列,patterns 包含與主題元素匹配的模式。如果子模式之一是 MatchStar 節點,則匹配可變長度序列,否則匹配固定長度序列。

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

在 3.10 版新加入.

class ast.MatchStar(name)

以可變長度匹配序列模式匹配序列的其餘部分。如果 name 不是 None,則如果整體序列模式成功,則包含其餘序列元素的串列將綁定到該名稱。

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

在 3.10 版新加入.

class ast.MatchMapping(keys, patterns, rest)

匹配對映模式。keys 是運算式節點的序列。patterns 是相應的模式節點序列。rest 是一個可選名稱,可以指定它來捕獲剩餘的對映元素。允許的鍵運算式受到匹配陳述式文件中所述的限制。

如果主題是對映,所有求值出的鍵運算式都存在於對映中,並且與每個鍵對應的值與相應的子模式匹配,則此模式成功。如果 rest 不是 None,則如果整體對映模式成功,則包含其餘對映元素的字典將綁定到該名稱。

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

在 3.10 版新加入.

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

匹配類別模式。cls 是一個給定要匹配的名義類別 (nominal class) 的運算式。patterns 是要與類別定義的模式匹配屬性序列進行匹配的模式節點序列。kwd_attrs 是要匹配的附加屬性序列(在類別模式中指定為關鍵字引數),kwd_patterns 是相應的模式(在類別模式中指定為關鍵字的值)。

如果主題是指定類別的實例,所有位置模式都與相應的類別定義屬性匹配,並且任何指定的關鍵字屬性與其相應模式匹配,則此模式成功。

注意:類別可以定義一個回傳 self 的特性 (property),以便將模式節點與正在匹配的實例進行匹配。一些內建型別也以這種方式匹配,如同匹配陳述式文件中所述。

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

在 3.10 版新加入.

class ast.MatchAs(pattern, name)

匹配的 「as 模式 (as-pattern)」,為捕獲模式 (capture pattern) 或通配模式 (wildcard pattern)。pattern 包含主題將與之匹配的匹配模式。如果模式為 None,則該節點代表捕獲模式(即裸名 (bare name))並且始終會成功。

name 屬性包含模式成功時將綁定的名稱。如果 nameNone,則 pattern 也必須為 None,並且節點代表通配模式。

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

在 3.10 版新加入.

class ast.MatchOr(patterns)

匹配的 「or 模式 (or-pattern)」。 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=[])

在 3.10 版新加入.

型別參數 (type parameters)

型別參數可以存在於類別、函式和型別別名上。

class ast.TypeVar(name, bound)

一個 typing.TypeVarname 是型別變數的名稱。bound 是(如果有存在的)界限 (bound) 或約束 (constraint)。如果 bound 是一個 Tuple,它代表約束;否則它代表界限。

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

在 3.12 版新加入.

class ast.ParamSpec(name)

A typing.ParamSpecname 是參數規範的名稱。

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

在 3.12 版新加入.

class ast.TypeVarTuple(name)

一個 typing.TypeVarTuplename 是型別變數元組的名稱。

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

在 3.12 版新加入.

函式和類別定義

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

一個函式定義。

  • name 是函式名稱的原始字串。

  • args 是一個 arguments 節點。

  • body 是函式內節點的串列。

  • decorator_list 是要應用的裝飾器串列,在最外層者會被儲存在首位(即串列中首位將會是最後一個被應用的那個)。

  • returns 是回傳註釋。

  • type_params型別參數的串列。

type_comment

type_comment 是一個可選字串,其中的註解為型別註釋。

在 3.12 版的變更: 新增了 type_params

class ast.Lambda(args, body)

lambda 是可以在運算式內使用的最小函式定義。與 FunctionDef 不同,body 保存單個節點。

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

函式的引數。

  • posonlyargsargskwonlyargsarg 節點的串列。

  • varargkwarg 是單個 arg 節點,指的是 *args, **kwargs 參數。

  • kw_defaults 是僅限關鍵字引數的預設值串列。如果其中某個為 None,則相應參數就會是必要的。

  • defaults 是可以按位置傳遞的引數的預設值串列。如果預設值較少,則它們對應於最後 n 個引數。

class ast.arg(arg, annotation, type_comment)

串列中的單個引數。arg 是引數名稱的原始字串,annotation 是它的註釋,例如 Name 節點。

type_comment

type_comment 是一個可選字串,其註解為型別註釋

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

一個 return 陳述式。

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

一個 yieldyield from 運算式。因為這些是運算式,所以如果不使用發送回來的值,則必須將它們包裝在 Expr 節點中。

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

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

globalnonlocal 陳述式。names 是原始字串的串列。

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

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

一個類別定義。

  • name 是類別名的原始字串

  • bases 是被顯式指定的基底類別節點串列。

  • keywords 是一個 keyword 節點的串列,主要用於 'metaclass'(元類別)。如 PEP-3115 所述,其他關鍵字將被傳遞到 metaclass。

  • body 是表示類別定義中程式碼的節點串列。

  • decorator_list 是一個節點串列,如 FunctionDef 中所示。

  • type_params型別參數的串列。

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

在 3.12 版的變更: 新增了 type_params

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 主體 (body) 中有效。

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

async for 迴圈和 async with 情境管理器。它們分別具有與 ForWith 相同的欄位。僅在 AsyncFunctionDef 主體中有效。

備註

當字串被 ast.parse() 剖析時,回傳樹的運算子節點(ast.operatorast.unaryopast.cmpop、:class: ast.boolopast.expr_context)將是單例。對其中之一的更改將反映在所有其他出現的相同值中(例如 ast.Add)。

ast 輔助程式

除了節點類別之外,ast 模組還定義了這些用於遍歷 (traverse) 抽象語法樹的實用函式和類別:

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

將原始碼剖析為 AST 節點。相當於 compile(source, filename, mode, ast.PyCF_ONLY_AST)

如果給定 type_comments=True,剖析器將被修改為檢查並回傳 PEP 484PEP 526 指定的型別註釋。這相當於將 ast.PyCF_TYPE_COMMENTS 新增到傳遞給 compile() 的旗標中。這將報告錯誤型別註釋的語法錯誤。如果沒有此旗標,型別註釋將被忽略,並且所選 AST 節點上的 type_comment 欄位將始終為 None。此外,# type: ignore 註釋的位置將作為 Moduletype_ignores 屬性回傳(否則它始終是一個空串列)。

此外,如果 mode'func_type',則輸入語法將會依據 PEP 484「簽名型別註解 (signature type comments)」而被修改,例如 (str, int) -> List[str]

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

如果來源包含 null 字元 (\0),則會引發 ValueError

警告

請注意,成功將原始碼剖析為 AST 物件並不能保證提供的原始碼是可以執行的有效 Python 程式碼,因為編譯步驟可能會引發進一步的 SyntaxError 例外。例如,原始的 return 42 為 return 陳述式生成一個有效的 AST 節點,但它不能單獨編譯(它需要位於函式節點內)。

特別是 ast.parse() 不會執行任何範圍檢查,而編譯步驟才會執行此操作。

警告

由於 Python AST 編譯器中的堆疊 (stack) 深度限制,太大或太複雜的字串可能會導致 Python 直譯器崩潰。

在 3.8 版的變更: 新增 type_commentsmode='func_type'feature_version

ast.unparse(ast_obj)

反剖析 ast.AST 物件並生成一個帶有程式碼的字串,如果使用 ast.parse() 剖析回來,該程式碼將生成等效的 ast.AST 物件。

警告

生成的程式碼字串不一定等於生成 ast.AST 物件的原始程式碼(沒有任何編譯器最佳化,例如常數元組/凍結集合)。

警告

嘗試剖析高度複雜的運算式會導致 RecursionError

在 3.9 版新加入.

ast.literal_eval(node_or_string)

為僅包含 Python 文本或容器之顯示的運算式節點或字串來求值。提供的字串或節點只能包含以下 Python 文本結構:字串、位元組、數字、元組、串列、字典、集合、布林值、NoneEllipsis

這可用於為包含 Python 值的字串求值,而無需自己剖析這些值。它無法計算任意複雜的運算式,例如涉及運算子或索引。

該函式過去被記錄為「安全」,但沒有定義其含義,這有點誤導讀者,它是特別設計為不去執行 Python 程式碼,與更通用的 eval() 不同。沒有命名空間、沒有名稱查找、也沒有呼叫的能力。但它也不能免受攻擊:相對較小的輸入可能會導致記憶體耗盡或 C 堆疊耗盡,從而導致行程崩潰。某些輸入也可能會出現 CPU 消耗過多而導致拒絕服務的情況。因此不建議在不受信任的資料上呼叫它。

警告

由於 Python AST 編譯器的堆疊深度限制,Python 直譯器可能會崩潰。

它可能會引發 ValueErrorTypeErrorSyntaxErrorMemoryErrorRecursionError,具體取決於格式錯誤的輸入。

在 3.2 版的變更: 現在允許位元組和集合文本 (set literal)。

在 3.9 版的變更: 現在支援使用 'set()' 建立空集合。

在 3.10 版的變更: 對於字串輸入,前導空格和定位字元 (tab) 現在已被去除。

ast.get_docstring(node, clean=True)

回傳給定 node 的文件字串 (docstring)(必須是 FunctionDefAsyncFunctionDefClassDefModule 節點)或如果它沒有文件字串則為 None。如果 clean 為 true,則使用 inspect.cleandoc() 清理文件字串的縮排。

在 3.5 版的變更: 目前已支援 AsyncFunctionDef

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

獲取生成 nodesource 的原始碼片段。如果某些位置資訊(linenoend_linenocol_offsetend_col_offset)遺漏,則回傳 None

如果 paddedTrue,則多列陳述式的第一列將用空格填充 (padded) 以匹配其原始位置。

在 3.8 版新加入.

ast.fix_missing_locations(node)

當你使用 compile() 編譯節點樹時,對於每個有支援 linenocol_offset 屬性之節點,編譯器預期他們的這些屬性都要存在。填入生成的節點相當繁瑣,因此該輔助工具透過將這些屬性設定為父節點的值,在尚未設定的地方遞迴地新增這些屬性。它從 node 開始遞迴地作用。

ast.increment_lineno(node, n=1)

將樹中從 node 開始的每個節點的列號和結束列號增加 n。這對於「移動程式碼」到檔案中的不同位置很有用。

ast.copy_location(new_node, old_node)

如果可行,將原始位置(linenocol_offsetend_linenoend_col_offset )從 old_node 複製到 new_node,並回傳 new_node

ast.iter_fields(node)

node 上存在的 node._fields 中的每個欄位生成一個 (fieldname, value) 元組。

ast.iter_child_nodes(node)

生成 node 的所有直接子節點,即作為節點的所有欄位以及作為節點串列欄位的所有項目。

ast.walk(node)

遞迴地生成樹中從 node 開始的所有後代節點(包括 node 本身),不按指定順序。如果你只想就地修改節點而不關心情境,這非常有用。

class ast.NodeVisitor

節點訪問者基底類別,它遍歷抽象語法樹並為找到的每個節點呼叫訪問者函式。該函式可能會回傳一個由 visit() 方法轉發的值。

這個類別應該被子類別化,子類別新增訪問者方法。

visit(node)

訪問一個節點。預設實作呼叫名為 self.visit_classname 的方法,其中 classname 是節點類別的名稱,或者在該方法不存在時呼叫 generic_visit()

generic_visit(node)

該訪問者對該節點的所有子節點呼叫 visit()

請注意,除非訪問者呼叫 generic_visit() 或訪問它們本身,否則不會訪問具有自定義訪問者方法的節點之子節點。

visit_Constant(node)

處理所有常數節點。

如果你想在遍歷期間將變更應用 (apply) 於節點,請不要使用 NodeVisitor。為此,有個允許修改的特殊遍歷訪問者工具 NodeTransformer

在 3.8 版之後被棄用: visit_Num()visit_Str()visit_Bytes()visit_NameConstant()visit_Ellipsis() 方法現已棄用,並且不會在未來的Python 版本中被呼叫。新增 visit_Constant() 方法來處理所有常數節點。

class ast.NodeTransformer

一個 NodeVisitor 子類別,它會遍歷抽象語法樹並允許修改節點。

NodeTransformer 將遍歷 AST 並使用訪問者方法的回傳值來替換或刪除舊節點。如果訪問者方法的回傳值為 None,則該節點將從其位置中刪除,否則將被替換為回傳值。回傳值可能是原始節點,在這種情況下不會發生替換。

下面是一個示範用的 transformer,它將查找所有出現名稱 (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() 方法。

對於屬於陳述式總集 (collection) 一部分的節點(適用於所有陳述式節點),訪問者還可以回傳節點串列,而不僅僅是單個節點。

如果 NodeTransformer 引進了新節點(不屬於原始樹的一部分),但沒有給它們提供位置資訊(例如 lineno),則應使用新的子樹呼叫 fix_missing_locations() 以重新計算位置資訊:

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

你通常會像這樣使用 transformer:

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

回傳 node 中樹的格式化傾印 (formatted dump),這主要用於除錯。如果 annotate_fields 為 true(為預設值),則回傳的字串將顯示欄位的名稱和值。如果 annotate_fields 為 false,則透過省略明確的欄位名稱,結果字串將更加縮減簡潔。預設情況下,不會傾印列號和行偏移量等屬性。如果需要,可以設定 include_attributes 為 true。

如果 indent 是非負整數或字串,那麼樹將使用該縮排級別來做漂亮印出 (pretty-print)。縮排級別 0、負數或 "" 只會插入換列符號 (newlines)。None(預設值)代表選擇單列表示。使用正整數縮排可以在每個級別縮排相同數量的空格。如果 indent 是一個字串(例如 "\t"),則該字串用於縮排每個級別。

在 3.9 版的變更: 新增 indent 選項。

編譯器旗標

可以將以下旗標傳遞給 compile() 以變更對程式的編譯效果:

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

啟用對最高階 awaitasync forasync with 和非同步綜合運算的支援。

在 3.8 版新加入.

ast.PyCF_ONLY_AST

生成並回傳抽象語法樹,而不是回傳已編譯的程式碼物件。

ast.PyCF_TYPE_COMMENTS

啟用對 PEP 484PEP 526 樣式型別註釋的支援 (# type: <type>, # type: ignore <stuff>)。

在 3.8 版新加入.

命令列用法

在 3.9 版新加入.

ast 模組可以作為腳本從命令列執行,可以像這樣簡單地做到:

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

以下選項可被接受:

-h, --help

顯示幫助訊息並退出。

-m <mode>
--mode <mode>

指定必須編譯哪種類型的程式碼,像是 parse() 中的 mode 引數。

--no-type-comments

不要剖析型別註解。

-a, --include-attributes

包括列號和行偏移量等屬性。

-i <indent>
--indent <indent>

AST 中節點的縮進(空格數)。

如果指定了 infile,則其內容將被剖析為 AST 並傾印 (dump) 到 stdout。否則會從 stdin 讀取內容。

也參考

Green Tree Snakes 是一個外部文件資源,提供了有關使用 Python AST 的詳細資訊。

ASTTokens 使用生成它們的原始碼中的標記和文本的位置來註釋 Python AST。這對於進行原始碼轉換的工具很有幫助。

leoAst.py unifies the token-based and parse-tree-based views of python programs by inserting two-way links between tokens and ast nodes.

LibCST 將程式碼剖析為具體語法樹 (Concrete Syntax Tree),看起來像 ast 樹並保留所有格式詳細資訊。它對於建置自動重構 (codemod) 應用程式和 linter 非常有用。

Parso is a Python parser that supports error recovery and round-trip parsing for different Python versions (in multiple Python versions). Parso is also able to list multiple syntax errors in your Python file.