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)
         | Interpolation(expr value, constant str, int conversion, expr? format_spec)
         | JoinedStr(expr* values)
         | TemplateStr(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-indexed,所以第一行是第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.14 版更改: AST 節點的 __repr__() 輸出包括節點欄位的值。

自 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" mode 下,由 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() 生成的節點型別。

body 是一個list,包含語句節點

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

舊式函式型別註釋的表示,因為 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 版本加入。

字面值

class ast.Constant(value)

一個常量值。Constant 字面值的 value 屬性包含它所代表的 Python 物件。所代表的值可以是 strbytesintfloatcomplexbool 的例項,以及常量 NoneEllipsis

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

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

  • value 是任意表達式節點(例如字面值、變數或函式呼叫)。

  • conversion 是一個整數

    • -1: 無格式化

    • 97 (ord('a')): !a ASCII 格式化

    • 114 (ord('r')): !r repr() 格式化

    • 115 (ord('s')): !s string 格式化

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

class ast.JoinedStr(values)

一個 f-string,由一系列 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.TemplateStr(values, /)

在 3.14 版本加入。

表示模板字串字面值的節點,由一系列 InterpolationConstant 節點組成。這些節點可以按任何順序排列,並且不必交錯。

>>> expr = ast.parse('t"{name} finished {place:ordinal}"', mode='eval')
>>> print(ast.dump(expr, indent=4))
Expression(
    body=TemplateStr(
        values=[
            Interpolation(
                value=Name(id='name', ctx=Load()),
                str='name',
                conversion=-1),
            Constant(value=' finished '),
            Interpolation(
                value=Name(id='place', ctx=Load()),
                str='place',
                conversion=-1,
                format_spec=JoinedStr(
                    values=[
                        Constant(value='ordinal')]))]))
class ast.Interpolation(value, str, conversion, format_spec=None)

在 3.14 版本加入。

表示模板字串字面值中單個插值欄位的節點。

  • value 是任何表示式節點(例如字面值、變數或函式呼叫)。其含義與 FormattedValue.value 相同。

  • str 是一個包含插值表示式文字的常量。

  • conversion 是一個整數

    • -1: 無轉換

    • 97 (ord('a')): !a ASCII 轉換

    • 114 (ord('r')): !r repr() 轉換

    • 115 (ord('s')): !s string 轉換

    其含義與 FormattedValue.conversion 相同。

  • format_spec 是一個 JoinedStr 節點,表示值的格式,如果未指定格式,則為 Noneconversionformat_spec 可以同時設定。其含義與 FormattedValue.format_spec 相同。

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 儲存本節中的其他節點之一,即 ConstantNameLambdaYieldYieldFrom 節點。

>>> 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 是一個給出屬性名稱的裸字串,ctx 根據對屬性的操作是 LoadStore 還是 Del

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

一個命名錶達式。這個 AST 節點由賦值表示式運算子(也稱為海象運算子)產生。與 Assign 節點中的第一個引數可以是多個節點不同,在這裡 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 並且包含一個 Slicectx 根據對下標執行的操作是 LoadStore 還是 Del

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

常規切片(形式為 lower: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)是表示將對每個項進行求值的部分的單個節點。

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()),
                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。在下面的例子中,target 是一個代表 xName 節點(帶有 Store 上下文),opAddvalue 是一個值為 1 的 Constant

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

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

一個 raise 語句。exc 是要引發的異常物件,通常是 CallName,對於獨立的 raise 則為 Nonecauseraise x from yy 的可選部分。

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

一個匯入語句。names 是一個 alias 節點列表。

>>> print(ast.dump(ast.parse('import x,y,z'), indent=4))
Module(
    body=[
        Import(
            names=[
                alias(name='x'),
                alias(name='y'),
                alias(name='z')])])
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 中沒有特殊的表示形式,而是作為前一個 If 節點的 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 包含迴圈賦值的變數,可以是單個 Name, Tuple, List, AttributeSubscript 節點。 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_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())]))])])

模式匹配

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 屬性包含一個表示式,如果模式匹配成功,該表示式將被求值。

如果模式匹配成功且守衛表示式的求值結果為真,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 是一個可選名稱,可用於捕獲剩餘的對映元素。允許的鍵表示式受到 match 語句文件中所述的限制。

如果主體是對映,所有求值後的鍵表示式都存在於對映中,並且每個鍵對應的值都與相應的子模式匹配,則此模式匹配成功。如果 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 的屬性,以便將模式節點與被匹配的例項進行匹配。如 match 語句文件所述,一些內建型別也以這種方式進行匹配。

>>> print(ast.dump(ast.parse("""
... match x:
...     case Point2D(0, 0):
...         ...
...     case Point3D(x=0, y=0, z=0):
...         ...
... """), indent=4))
Module(
    body=[
        Match(
            subject=Name(id='x', ctx=Load()),
            cases=[
                match_case(
                    pattern=MatchClass(
                        cls=Name(id='Point2D', ctx=Load()),
                        patterns=[
                            MatchValue(
                                value=Constant(value=0)),
                            MatchValue(
                                value=Constant(value=0))]),
                    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)

一個匹配“or-pattern”。一個 or-pattern 會將其每個子模式依次與主體進行匹配,直到有一個匹配成功。此時,or-pattern 被視為成功。如果所有子模式都匹配失敗,則 or-pattern 失敗。 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.TypeIgnore(lineno, tag)

位於 lineno 行的 # type: ignore 註釋。 tag 是由 # type: ignore <tag> 形式指定的可選標籤。

>>> print(ast.dump(ast.parse('x = 1 # type: ignore', type_comments=True), indent=4))
Module(
    body=[
        Assign(
            targets=[
                Name(id='x', ctx=Store())],
            value=Constant(value=1))],
    type_ignores=[
        TypeIgnore(lineno=1, tag='')])
>>> print(ast.dump(ast.parse('x: bool = 1 # type: ignore[assignment]', type_comments=True), indent=4))
Module(
    body=[
        AnnAssign(
            target=Name(id='x', ctx=Store()),
            annotation=Name(id='bool', ctx=Load()),
            value=Constant(value=1),
            simple=1)],
    type_ignores=[
        TypeIgnore(lineno=1, tag='[assignment]')])

備註

type_comments 引數設定為 False(預設值)時,不會生成 TypeIgnore 節點。更多詳情請參閱 ast.parse()

在 3.8 版本加入。

型別形參

型別形參可以存在於類、函式和類型別名中。

class ast.TypeVar(name, bound, default_value)

一個 typing.TypeVarname 是型別變數的名稱。 bound 是邊界或約束(如果有的話)。如果 bound 是一個 Tuple,它代表約束;否則它代表邊界。 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)

函式的引數。

  • posonlyargs, argskwonlyargsarg 節點的列表。

  • 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.operator, ast.unaryop, ast.cmpop, ast.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),其中如果 optimize <= 0FLAGS_VALUEast.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 版本上執行時相同。

如果 source 包含空字元 (\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 物件的原始程式碼(在沒有任何編譯器最佳化的情況下,例如常量元組/frozensets)。

警告

嘗試反解析一個高度複雜的表示式將導致 RecursionError

在 3.9 版本中新增。

ast.literal_eval(node_or_string)

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

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

過去,該函式曾被記錄為“安全的”,但沒有定義這意味著什麼。這是誤導性的。這個函式被專門設計為不執行 Python 程式碼,與更通用的 eval() 不同。它沒有名稱空間、沒有名稱查詢,也沒有呼叫外部函式的能力。但它並非不受攻擊:一個相對較小的輸入可能導致記憶體耗盡或 C 棧耗盡,從而使程序崩潰。對於某些輸入,還可能存在過度的 CPU 消耗拒絕服務攻擊。因此,不建議在不受信任的資料上呼叫它。

警告

由於 Python 的 AST 編譯器存在棧深度限制,可能會導致 Python 直譯器崩潰。

根據格式錯誤的輸入,它可能引發 ValueError, TypeError, SyntaxError, MemoryErrorRecursionError

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

獲取生成 nodesource 的原始碼片段。如果缺少某些位置資訊(lineno, end_lineno, col_offsetend_col_offset),則返回 None

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

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

如果可能,將源位置(lineno, col_offset, end_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)

處理所有常量節點。

如果你想在遍歷期間對節點進行更改,請不要使用 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_empty 為 false(預設值),可選的空列表將從輸出中省略。可選的 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 版本加入。

ast.compare(a, b, /, *, compare_attributes=False)

遞迴地比較兩個 AST。

compare_attributes 影響 AST 屬性是否在比較中被考慮。如果 compare_attributesFalse(預設值),則屬性被忽略。否則它們必須全部相等。這個選項對於檢查 AST 是否在結構上相等,但在空格或類似細節上有所不同很有用。屬性包括行號和列偏移。

在 3.14 版本加入。

命令列用法

在 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 中節點的縮排(空格數)。

--feature-version <version>

Python 版本,格式為 3.x(例如,3.10)。預設為直譯器的當前版本。

在 3.14 版本加入。

-O <level>
--optimize <level>

解析器的最佳化級別。預設為不最佳化。

在 3.14 版本加入。

--show-empty

顯示空列表和值為 None 的欄位。預設為不顯示空物件。

在 3.14 版本加入。

如果指定了 infile,其內容將被解析為 AST 並轉儲到標準輸出。否則,內容從標準輸入讀取。

參見

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

ASTTokens 會為 Python AST 添加註釋,標明生成它們的標記和文字在原始碼中的位置。這對於進行原始碼轉換的工具很有幫助。

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

LibCST 將程式碼解析為具體語法樹(Concrete Syntax Tree),它看起來像一個 ast 樹並保留了所有格式化細節。這對於構建自動重構(codemod)應用程式和 linter 非常有用。

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