ast — 抽象語法樹

原始碼: Lib/ast.py


ast 模組幫助 Python 應用程式處理 Python 抽象語法樹。 抽象語法本身可能會隨著每個 Python 版本的釋出而更改;此模組有助於以程式設計方式找出當前語法的樣子。

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

抽象語法

抽象語法目前定義如下

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

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

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

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

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

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

          | Match(expr subject, match_case* cases)

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

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

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

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

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

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

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

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

    expr_context = Load | Store | Del

    boolop = And | Or

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

    unaryop = Invert | Not | UAdd | USub

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

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

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

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

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

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

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

    withitem = (expr context_expr, expr? optional_vars)

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

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

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

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

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

    type_ignore = TypeIgnore(int lineno, string tag)

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

節點類

class ast.AST

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

抽象語法中為每個左側符號定義一個類(例如,ast.stmtast.expr)。 此外,為右側的每個建構函式定義一個類;這些類繼承自左側樹的類。 例如,ast.BinOp 繼承自 ast.expr。 對於具有備選方案(又名“和”)的生成規則,左側類是抽象的:僅建立特定建構函式節點的例項。

_fields

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

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

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

_field_types

每個具體類上的 _field_types 屬性是一個字典,它將欄位名稱(也列在 _fields 中)對映到它們的型別。

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

3.13 版本新增。

lineno
col_offset
end_lineno
end_col_offset

ast.exprast.stmt 子類的例項具有 linenocol_offsetend_linenoend_col_offset 屬性。linenoend_lineno 是源文字跨度的第一個和最後一個行號(從 1 開始索引,因此第一行是行 1),而 col_offsetend_col_offset 是生成節點的第一個和最後一個標記的相應 UTF-8 位元組偏移量。 記錄 UTF-8 偏移量是因為解析器在內部使用 UTF-8。

請注意,編譯器不需要結束位置,因此是可選的。 結束偏移量在最後一個符號之後,例如,可以使用 source_line[node.col_offset : node.end_col_offset] 獲取單行表示式節點的源片段。

ast.T 的建構函式按如下方式解析其引數

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

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

例如,要建立和填充 ast.UnaryOp 節點,可以使用

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

如果語法中可選的欄位在建構函式中被省略,它將預設為 None。如果省略列表欄位,則預設為空列表。如果省略型別為 ast.expr_context 的欄位,它將預設為 Load()。如果省略任何其他欄位,則會引發 DeprecationWarning,並且 AST 節點將不包含此欄位。在 Python 3.15 中,此條件將引發錯誤。

在 3.8 版本中更改:ast.Constant 現在用於所有常量。

在 3.9 版本中更改: 簡單索引用它們的值表示,擴充套件切片用元組表示。

自 3.8 版本起已棄用: 舊類 ast.Numast.Strast.Bytesast.NameConstantast.Ellipsis 仍然可用,但它們將在未來的 Python 版本中被刪除。在此期間,例項化它們將返回不同類的例項。

自 3.9 版本起已棄用: 舊類 ast.Indexast.ExtSlice 仍然可用,但它們將在未來的 Python 版本中被刪除。在此期間,例項化它們將返回不同類的例項。

自 3.13 版本起已棄用,將在 3.15 版本中刪除: 之前的 Python 版本允許建立缺少必需欄位的 AST 節點。同樣,AST 節點建構函式允許將任意關鍵字引數設定為 AST 節點的屬性,即使它們與 AST 節點的任何欄位都不匹配。此行為已被棄用,並將在 Python 3.15 中刪除。

注意

此處顯示的特定節點類的描述最初改編自出色的 Green Tree Snakes 專案及其所有貢獻者。

根節點

class ast.Module(body, type_ignores)

一個 Python 模組,與 檔案輸入 相同。由預設 "exec" *模式* 中的 ast.parse() 生成的節點型別。

body 是模組的 list 語句

type_ignores 是模組的型別忽略註釋的 list;有關更多詳細資訊,請參閱 ast.parse()

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

一個單獨的 Python 表示式輸入。當 *mode* 為 "eval" 時,由 ast.parse() 生成的節點型別。

body 是一個單獨的節點,屬於表示式型別之一。

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

一個單獨的 互動式輸入,如 互動模式 中所示。當 *mode* 為 "single" 時,由 ast.parse() 生成的節點型別。

bodylist 語句節點

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

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

此類型別註釋如下所示

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

argtypeslist 表示式節點

returns 是單個 表示式節點

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

在 3.8 版本中新增。

字面量

class ast.Constant(value)

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

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

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

  • value 是任何表示式節點(例如字面量、變數或函式呼叫)。

  • conversion 是一個整數

    • -1: 無格式化

    • 115: !s 字串格式化

    • 114: !r repr 格式化

    • 97: !a ascii 格式化

  • format_spec 是表示值的格式化的 JoinedStr 節點,如果沒有指定格式,則為 Noneconversionformat_spec 可以同時設定。

class ast.JoinedStr(values)

一個 f 字串,由一系列 FormattedValueConstant 節點組成。

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

一個列表或元組。elts 儲存表示元素的節點列表。ctx 如果容器是賦值目標(即 (x,y)=something),則為 Store,否則為 Load

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

一個集合。elts 儲存表示集合元素的節點列表。

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

一個字典。keysvalues 分別儲存代表鍵和值的節點列表,順序匹配(呼叫 dictionary.keys()dictionary.values() 時返回的結果)。

當使用字典字面量進行字典解包時,要展開的表示式會放在 values 列表中,而 keys 中相應位置的值為 None

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

變數

class ast.Name(id, ctx)

一個變數名。id 以字串形式儲存變數名,而 ctx 是以下型別之一。

class ast.Load
class ast.Store
class ast.Del

變數引用可以用於載入變數的值、為變數賦予新值或刪除變數。變數引用被賦予一個上下文,以區分這些情況。

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

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

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

一個 *var 變數引用。value 儲存該變數,通常是一個 Name 節點。當構建帶有 *argsCall 節點時,必須使用此型別。

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

表示式

class ast.Expr(value)

當一個表示式(如函式呼叫)作為語句本身出現,其返回值未被使用或儲存時,它會被包裝在這個容器中。value 儲存本節中的其他節點之一,一個 Constant、一個 Name、一個 Lambda、一個 Yield 或一個 YieldFrom 節點。

>>> print(ast.dump(ast.parse('-a'), indent=4))
Module(
    body=[
        Expr(
            value=UnaryOp(
                op=USub(),
                operand=Name(id='a', ctx=Load())))])
class ast.UnaryOp(op, operand)

一個一元運算。op 是運算子,而 operand 是任何表示式節點。

class ast.UAdd
class ast.USub
class ast.Not
class ast.Invert

一元運算子標記。Notnot 關鍵字,Invert~ 運算子。

>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4))
Expression(
    body=UnaryOp(
        op=Not(),
        operand=Name(id='x', ctx=Load())))
class ast.BinOp(left, op, right)

一個二元運算(如加法或除法)。op 是運算子,而 leftright 是任何表示式節點。

>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4))
Expression(
    body=BinOp(
        left=Name(id='x', ctx=Load()),
        op=Add(),
        right=Name(id='y', ctx=Load())))
class ast.Add
class ast.Sub
class ast.Mult
class ast.Div
class ast.FloorDiv
class ast.Mod
class ast.Pow
class ast.LShift
class ast.RShift
class ast.BitOr
class ast.BitXor
class ast.BitAnd
class ast.MatMult

二元運算子標記。

class ast.BoolOp(op, values)

一個布林運算,‘or’ 或 ‘and’。opOrAndvalues 是涉及的值。具有相同運算子的連續運算,例如 a or b or c,將被摺疊成一個具有多個值的節點。

這不包括 not,它是一個 UnaryOp

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

布林運算子標記。

class ast.Compare(left, ops, comparators)

兩個或多個值的比較。left 是比較中的第一個值,ops 是運算子列表,而 comparators 是比較中第一個元素之後的值列表。

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

比較運算子標記。

class ast.Call(func, args, keywords)

函式呼叫。func 是函式,通常是一個 NameAttribute 物件。關於引數

  • args 包含按位置傳遞的引數列表。

  • keywords 包含表示按關鍵字傳遞的引數的 keyword 物件列表。

argskeywords 引數是可選的,預設為空列表。

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

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

class ast.IfExp(test, body, orelse)

一個諸如 a if b else c 的表示式。每個欄位都包含一個單獨的節點,因此在以下示例中,所有三個都是 Name 節點。

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

屬性訪問,例如 d.keysvalue 是一個節點,通常是 Nameattr 是一個給出屬性名稱的裸字串,並且 ctxLoadStoreDel,具體取決於如何對屬性執行操作。

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

命名錶達式。此 AST 節點由賦值表示式運算子(也稱為海象運算子)生成。與 Assign 節點中第一個引數可以是多個節點不同,在這種情況下,targetvalue 都必須是單個節點。

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

在 3.8 版本中新增。

下標

class ast.Subscript(value, slice, ctx)

一個下標,例如 l[1]value 是下標物件(通常是序列或對映)。slice 是索引、切片或鍵。它可以是一個 Tuple 並且包含一個 SlicectxLoadStoreDel,具體取決於使用下標執行的操作。

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

常規切片(形式為 lower:upperlower:upper:step)。只能出現在 Subscriptslice 欄位中,可以直接出現,也可以作為 Tuple 的元素出現。

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

推導式

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

列表和集合推導式、生成器表示式和字典推導式。elt(或 keyvalue)是表示將為每個專案評估的部分的單個節點。

generatorscomprehension 節點的列表。

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

推導式中的一個 for 子句。target 是用於每個元素的引用 - 通常是 NameTuple 節點。iter 是要迭代的物件。ifs 是測試表達式的列表:每個 for 子句可以有多個 ifs

is_async 表示推導式是非同步的(使用 async for 而不是 for)。該值是一個整數(0 或 1)。

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

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

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

語句

class ast.Assign(targets, value, type_comment)

賦值。targets 是一個節點列表,value 是一個單獨的節點。

targets 中的多個節點表示將相同的值分配給每個節點。解包透過在 targets 中放置一個 TupleList 來表示。

type_comment

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

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

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

帶有型別註解的賦值。target 是一個單獨的節點,可以是 NameAttributeSubscriptannotation 是註解,例如 ConstantName 節點。value 是一個可選的單獨節點。

simple 始終為 0(表示“複雜”目標)或 1(表示“簡單”目標)。“簡單”目標僅由一個不出現在括號之間的 Name 節點組成;所有其他目標都被認為是複雜的。只有簡單的目標會出現在模組和類的 __annotations__ 字典中。

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

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

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

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

增廣賦值,例如 a += 1。在以下示例中,targetxName 節點(帶有 Store 上下文),opAddvalue 是值為 1 的 Constant

Assign 的目標不同,target 屬性不能是 TupleList 類。

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

一個 raise 語句。exc 是要引發的異常物件,通常是 CallName,或者對於獨立的 raise 來說是 Nonecauseraise x from y 中可選的 y 部分。

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

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

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

表示 del 語句。targets 是節點列表,例如 NameAttributeSubscript 節點。

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

一個 pass 語句。

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

透過 type 語句建立的類型別名name 是別名的名稱,type_params型別引數 的列表,value 是類型別名的值。

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

3.12 版本中新增。

其他僅適用於函式或迴圈內部的語句將在其他章節中描述。

匯入

class ast.Import(names)

一個匯入語句。namesalias 節點的列表。

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

表示 from x import ymodule 是 'from' 名稱的原始字串,不帶任何前導點,或者對於諸如 from . import foo 之類的語句,則為 Nonelevel 是一個整數,表示相對匯入的級別(0 表示絕對匯入)。

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

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

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

控制流

注意

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

class ast.If(test, body, orelse)

一個 if 語句。test 儲存單個節點,例如 Compare 節點。bodyorelse 各自儲存一個節點列表。

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

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

一個 for 迴圈。target 儲存迴圈賦值的變數,作為單個 NameTupleListAttributeSubscript 節點。iter 儲存要迴圈的專案,同樣作為單個節點。bodyorelse 包含要執行的節點列表。如果迴圈正常完成而不是透過 break 語句完成,則執行 orelse 中的節點。

type_comment

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

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

一個 while 迴圈。test 儲存條件,例如 Compare 節點。

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

breakcontinue 語句。

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

try 程式碼塊。所有屬性都是要執行的節點列表,除了 handlers,它是一個 ExceptHandler 節點的列表。

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

後跟 except* 子句的 try 程式碼塊。這些屬性與 Try 的相同,但 handlers 中的 ExceptHandler 節點被解釋為 except* 程式碼塊,而不是 except

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

在 3.11 版本中新增。

class ast.ExceptHandler(type, name, body)

單個 except 子句。type 是它將匹配的異常型別,通常是一個 Name 節點(或者對於捕獲所有異常的 except: 子句,則為 None)。name 是用於儲存異常的原始字串名稱,如果該子句沒有 as foo,則為 Nonebody 是節點列表。

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

with 程式碼塊。items 是表示上下文管理器的 withitem 節點列表,body 是上下文內部的縮排程式碼塊。

type_comment

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

class ast.withitem(context_expr, optional_vars)

with 程式碼塊中的單個上下文管理器。context_expr 是上下文管理器,通常是 Call 節點。optional_varsNameTupleList,用於表示 as foo 部分,如果未使用,則為 None

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

模式匹配

class ast.Match(subject, cases)

match 語句。subject 儲存匹配的主題(正在與 case 進行匹配的物件),cases 包含一個 match_case 節點的迭代器,其中包含不同的 case。

在 3.10 版本中新增。

class ast.match_case(pattern, guard, body)

match 語句中的單個 case 模式。pattern 包含將與主題進行匹配的匹配模式。請注意,為模式生成的 AST 節點與為表示式生成的節點不同,即使它們共享相同的語法。

guard 屬性包含一個表示式,如果模式與主題匹配,則會對其進行求值。

如果模式匹配且計算 guard 表示式的結果為 true,則 body 包含要執行的節點列表。

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

在 3.10 版本中新增。

class ast.MatchValue(value)

透過相等比較的匹配字面值或值模式。value 是一個表示式節點。允許的值節點如 match 語句文件中所述受到限制。如果匹配主題等於已評估的值,則此模式成功。

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

在 3.10 版本中新增。

class ast.MatchSingleton(value)

透過身份比較的匹配字面值模式。value 是要比較的單例:NoneTrueFalse。如果匹配主題是給定的常量,則此模式成功。

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

在 3.10 版本中新增。

class ast.MatchSequence(patterns)

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

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

在 3.10 版本中新增。

class ast.MatchStar(name)

在可變長度匹配序列模式中,匹配序列的其餘部分。如果 name 不是 None,則如果整個序列模式成功,則將包含剩餘序列元素的列表繫結到該名稱。

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

在 3.10 版本中新增。

class ast.MatchMapping(keys, patterns, rest)

一個匹配對映模式。 keys 是表示式節點的序列。 patterns 是對應的模式節點序列。 rest 是一個可選的名稱,可以指定用於捕獲剩餘的對映元素。 允許的鍵表示式受匹配語句文件中描述的限制。

如果主題是一個對映,所有計算出的鍵表示式都存在於該對映中,並且每個鍵對應的值與對應的子模式匹配,則此模式成功。如果 rest 不是 None,則當整體對映模式成功時,包含剩餘對映元素的字典將繫結到該名稱。

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

在 3.10 版本中新增。

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

一個匹配類模式。cls 是一個表示式,給出要匹配的名義類。patterns 是要針對類定義的模式匹配屬性序列進行匹配的模式節點序列。kwd_attrs 是要匹配的其他屬性序列(在類模式中指定為關鍵字引數),kwd_patterns 是相應的模式(在類模式中指定為關鍵字值)。

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

注意:類可以定義一個返回 self 的屬性,以便將模式節點與正在匹配的例項進行匹配。如匹配語句文件中所述,一些內建型別也以這種方式進行匹配。

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

在 3.10 版本中新增。

class ast.MatchAs(pattern, name)

一個匹配“as-pattern”,捕獲模式或萬用字元模式。 pattern 包含要與主題匹配的匹配模式。如果模式是 None,則該節點表示捕獲模式(即裸名稱),並且將始終成功。

name 屬性包含如果模式成功將繫結的名稱。如果 nameNone,則 pattern 也必須是 None,並且該節點表示萬用字元模式。

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

在 3.10 版本中新增。

class ast.MatchOr(patterns)

一個匹配“或-模式”。或-模式依次將其每個子模式與主題進行匹配,直到一個成功。然後,或-模式被視為成功。如果沒有一個子模式成功,則或-模式失敗。patterns 屬性包含將與主題匹配的匹配模式節點列表。

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

在 3.10 版本中新增。

型別引數

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

class ast.TypeVar(name, bound, default_value)

一個 typing.TypeVarname 是型別變數的名稱。 bound 是邊界或約束(如果有)。如果 boundTuple,則表示約束;否則表示邊界。default_value 是預設值;如果 TypeVar 沒有預設值,則此屬性將設定為 None

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

3.12 版本中新增。

在 3.13 版本中更改: 添加了 default_value 引數。

class ast.ParamSpec(name, default_value)

一個 typing.ParamSpecname 是引數規範的名稱。default_value 是預設值;如果 ParamSpec 沒有預設值,則此屬性將設定為 None

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

3.12 版本中新增。

在 3.13 版本中更改: 添加了 default_value 引數。

class ast.TypeVarTuple(name, default_value)

一個 typing.TypeVarTuplename 是型別變數元組的名稱。default_value 是預設值;如果 TypeVarTuple 沒有預設值,則此屬性將設定為 None

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

3.12 版本中新增。

在 3.13 版本中更改: 添加了 default_value 引數。

函式和類定義

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

一個函式定義。

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

  • args 是一個 arguments 節點。

  • body 是函式內部的節點列表。

  • decorator_list 是要應用的裝飾器列表,按最外層優先儲存(即,列表中的第一個將最後應用)。

  • returns 是返回註釋。

  • type_params型別引數 的列表。

type_comment

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

在 3.12 版本中更改: 添加了 type_params

class ast.Lambda(args, body)

lambda 是一個最小的函式定義,可以在表示式內部使用。 與 FunctionDef 不同,body 包含一個節點。

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

函式的引數。

  • posonlyargsargskwonlyargsarg 節點的列表。

  • varargkwarg 是單個 arg 節點,分別指向 *args**kwargs 引數。

  • kw_defaults 是僅限關鍵字引數的預設值列表。 如果其中一個是 None,則表示相應的引數是必需的。

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

class ast.arg(arg, annotation, type_comment)

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

type_comment

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

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

return 語句。

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

yieldyield from 表示式。 由於這些是表示式,如果未使用返回的值,則必須將其包裝在 Expr 節點中。

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

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

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

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

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

類定義。

  • name 是類名稱的原始字串。

  • bases 是顯式指定的基類的節點列表。

  • keywordskeyword 節點的列表,主要用於 “metaclass”。根據 PEP 3115,其他關鍵字將傳遞給元類。

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

  • decorator_list 是節點列表,與 FunctionDef 中的類似。

  • type_params型別引數 的列表。

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

在 3.12 版本中更改: 添加了 type_params

Async 和 await

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

async def 函式定義。 具有與 FunctionDef 相同的欄位。

在 3.12 版本中更改: 添加了 type_params

class ast.Await(value)

await 表示式。value 是它等待的內容。 僅在 AsyncFunctionDef 的主體中有效。

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

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

注意

當字串由 ast.parse() 解析時,返回的樹上的運算子節點(ast.operatorast.unaryopast.cmpopast.boolopast.expr_context 的子類)將是單例。對其中一個的更改將反映在相同值的所有其他出現中(例如 ast.Add)。

ast 助手

除了節點類之外,ast 模組還定義了以下用於遍歷抽象語法樹的實用函式和類

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

將原始碼解析為 AST 節點。等效於 compile(source, filename, mode, flags=FLAGS_VALUE, optimize=optimize),其中 FLAGS_VALUEoptimize <= 0 時為 ast.PyCF_ONLY_AST,否則為 ast.PyCF_OPTIMIZED_AST

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

此外,如果 mode'func_type',則輸入語法將被修改以對應於 PEP 484 “簽名型別註釋”,例如 (str, int) -> List[str]

feature_version 設定為元組 (major, minor) 將導致“盡力而為”地嘗試使用該 Python 版本的語法進行解析。例如,設定 feature_version=(3, 9) 將嘗試禁止解析 match 語句。目前,major 必須等於 3。支援的最低版本是 (3, 7)(並且這可能在未來的 Python 版本中增加);最高版本是 sys.version_info[0:2]。“盡力而為”的嘗試意味著不能保證解析(或解析的成功)與在與 feature_version 對應的 Python 版本上執行時相同。

如果原始碼包含空字元(\0),則會引發 ValueError

警告

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

特別是,ast.parse() 不會進行任何作用域檢查,而編譯步驟會進行這些檢查。

警告

由於 Python 的 AST 編譯器中的堆疊深度限制,可以使用足夠大/複雜的字串使 Python 直譯器崩潰。

在 3.8 版本中更改: 添加了 type_commentsmode='func_type'feature_version

在 3.13 版本中更改: feature_version 的最低支援版本現在是 (3, 7)。添加了 optimize 引數。

ast.unparse(ast_obj)

解析 ast.AST 物件並生成一個字串,其中包含如果使用 ast.parse() 解析回來則會產生等效 ast.AST 物件的程式碼。

警告

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

警告

嘗試解析高度複雜的表示式會導致 RecursionError

在 3.9 版本中新增。

ast.literal_eval(node_or_string)

評估表示式節點或僅包含 Python 字面值或容器顯示的字串。提供的字串或節點可能只包含以下 Python 字面值結構:字串、位元組、數字、元組、列表、字典、集合、布林值、NoneEllipsis

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

過去,此函式被記錄為“安全”,但沒有定義其含義。這是具有誤導性的。此函式專門設計為不執行 Python 程式碼,這與更通用的 eval() 不同。沒有名稱空間、沒有名稱查詢或呼叫能力。但是它並非沒有攻擊風險:相對較小的輸入可能會導致記憶體耗盡或 C 堆疊耗盡,從而導致程序崩潰。某些輸入還可能導致過多的 CPU 消耗拒絕服務。因此,不建議在不受信任的資料上呼叫它。

警告

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

它可能會根據格式錯誤的輸入引發 ValueErrorTypeErrorSyntaxErrorMemoryErrorRecursionError

在 3.2 版本中更改: 現在允許位元組和集合字面量。

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

在 3.10 版本中更改: 對於字串輸入,現在會去除前導空格和製表符。

ast.get_docstring(node, clean=True)

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

在 3.5 版本中更改: 現在支援 AsyncFunctionDef

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

獲取生成 *node* 的 *source* 的原始碼片段。如果缺少一些位置資訊(linenoend_linenocol_offsetend_col_offset),則返回 None

如果 *padded* 為 True,則多行語句的第一行將用空格填充,以匹配其原始位置。

在 3.8 版本中新增。

ast.fix_missing_locations(node)

當您使用 compile() 編譯節點樹時,編譯器期望每個支援它們的節點都有 linenocol_offset 屬性。對於生成的節點,填充這些屬性相當繁瑣,因此此輔助函式透過將它們設定為父節點的值,以遞迴方式為尚未設定這些屬性的節點新增這些屬性。它從 *node* 開始遞迴工作。

ast.increment_lineno(node, n=1)

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

ast.copy_location(new_node, old_node)

如果可能,將源位置(linenocol_offsetend_linenoend_col_offset)從 *old_node* 複製到 *new_node*,並返回 *new_node*。

ast.iter_fields(node)

為 *node* 中存在的每個 node._fields 中的欄位生成一個 (欄位名, 值) 的元組。

ast.iter_child_nodes(node)

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

ast.walk(node)

以未指定的順序遞迴生成從 *node* 開始的樹中的所有後代節點(包括 *node* 本身)。如果您只想就地修改節點而不關心上下文,這將非常有用。

class ast.NodeVisitor

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

這個類旨在被子類化,子類新增訪問者方法。

visit(node)

訪問一個節點。預設實現會呼叫名為 self.visit_classname 的方法,其中 *classname* 是節點類的名稱,如果該方法不存在,則呼叫 generic_visit()

generic_visit(node)

此訪問器在節點的所有子節點上呼叫 visit()

請注意,除非訪問器呼叫 generic_visit() 或自行訪問,否則具有自定義訪問器方法的節點的子節點將不會被訪問。

visit_Constant(node)

處理所有常量節點。

如果您想在遍歷期間對節點應用更改,請不要使用 NodeVisitor。為此,存在一個特殊的訪問器 (NodeTransformer),它允許修改。

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

class ast.NodeTransformer

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

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

這是一個示例轉換器,它將所有出現的名稱查詢(foo)重寫為 data['foo']

class RewriteName(NodeTransformer):

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

請記住,如果您正在操作的節點具有子節點,則必須自己轉換子節點或先為該節點呼叫 generic_visit() 方法。

對於屬於語句集合的節點(適用於所有語句節點),訪問器還可以返回節點列表,而不僅僅是單個節點。

如果 NodeTransformer 引入了新的節點(這些節點不是原始樹的一部分),而沒有給它們位置資訊(例如 lineno),則應使用新的子樹呼叫 fix_missing_locations(),以重新計算位置資訊

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

通常您像這樣使用轉換器

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

返回 node 中樹的格式化轉儲。這主要用於除錯目的。如果 annotate_fields 為 true(預設情況下),則返回的字串將顯示欄位的名稱和值。如果 annotate_fields 為 false,則結果字串將透過省略明確的欄位名稱而更緊湊。預設情況下不轉儲諸如行號和列偏移之類的屬性。如果需要,可以將 include_attributes 設定為 true。

如果 indent 是一個非負整數或字串,則樹將以該縮排級別進行漂亮列印。縮排級別為 0、負數或 "" 將僅插入換行符。None(預設值)選擇單行表示。使用正整數縮排表示每級縮排多個空格。如果 indent 是一個字串(例如 "\t"),則該字串用於縮排每個級別。

如果 show_emptyFalse(預設值),則空列表和為 None 的欄位將從輸出中省略。

在 3.9 版本中更改: 添加了 indent 選項。

在 3.13 版本中更改: 添加了 show_empty 選項。

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

編譯器標誌

以下標誌可以傳遞給 compile() 以更改程式編譯的效果

ast.PyCF_ALLOW_TOP_LEVEL_AWAIT

啟用對頂層 awaitasync forasync with 和非同步推導式的支援。

在 3.8 版本中新增。

ast.PyCF_ONLY_AST

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

ast.PyCF_OPTIMIZED_AST

返回的 AST 根據 compile()ast.parse() 中的 optimize 引數進行最佳化。

3.13 版本新增。

ast.PyCF_TYPE_COMMENTS

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

在 3.8 版本中新增。

命令列用法

在 3.9 版本中新增。

可以從命令列將 ast 模組作為指令碼執行。它就像

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

接受以下選項

-h, --help

顯示幫助訊息並退出。

-m <mode>
--mode <mode>

指定必須編譯的程式碼型別,類似於 parse() 中的 mode 引數。

--no-type-comments

不解析型別註釋。

-a, --include-attributes

包含行號和列偏移等屬性。

-i <indent>
--indent <indent>

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

如果指定了 infile,則將其內容解析為 AST 並轉儲到 stdout。否則,將從 stdin 讀取內容。

另請參閱

Green Tree Snakes,一個外部文件資源,其中包含有關使用 Python AST 的詳細資訊。

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

leoAst.py 透過在標記和 ast 節點之間插入雙向連結,統一了 Python 程式的基於標記的檢視和基於解析樹的檢視。

LibCST 將程式碼解析為看起來像 ast 樹並保留所有格式細節的具體語法樹。它對於構建自動化重構 (codemod) 應用程式和 linters 很有用。

Parso 是一個 Python 解析器,支援錯誤恢復和不同 Python 版本(在多個 Python 版本中)的往返解析。Parso 還能夠列出 Python 檔案中的多個語法錯誤。