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.stmt
或ast.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.expr
和ast.stmt
子類的例項具有lineno
、col_offset
、end_lineno
和end_col_offset
屬性。lineno
和end_lineno
是原始碼文字範圍的第一行和最後一行行號(1-indexed,所以第一行是第1行),而col_offset
和end_col_offset
是生成該節點的第一個和最後一個詞法單元對應的 UTF-8 位元組偏移量。記錄 UTF-8 偏移量是因為解析器內部使用 UTF-8。請注意,結束位置不是編譯器所必需的,因此是可選的。結束偏移量在最後一個符號*之後*,例如,可以使用
source_line[node.col_offset : node.end_col_offset]
獲取單行表示式節點的原始碼片段。
類
ast.T
的建構函式按以下方式解析其引數:如果存在位置引數,其數量必須與
T._fields
中的項數相同;它們將被賦值為這些名稱的屬性。如果存在關鍵字引數,它們將把同名屬性設定為給定的值。
例如,要建立並填充一個
ast.UnaryOp
節點,你可以使用:node = ast.UnaryOp(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.Num
、ast.Str
、ast.Bytes
、ast.NameConstant
和 ast.Ellipsis
仍然可用,但它們將在未來的 Python 版本中被移除。在此期間,例項化它們將返回一個不同類的例項。
自 3.9 版起不推薦使用: 舊的類 ast.Index
和 ast.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()
生成的節點型別。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()
生成的節點型別。>>> 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
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 物件。所代表的值可以是str
、bytes
、int
、float
、complex
和bool
的例項,以及常量None
和Ellipsis
。>>> 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
中。
- class ast.JoinedStr(values)¶
一個 f-string,由一系列
FormattedValue
和Constant
節點組成。>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4)) Expression( body=JoinedStr( values=[ Constant(value='sin('), FormattedValue( value=Name(id='a', ctx=Load()), conversion=-1), Constant(value=') is '), FormattedValue( value=Call( func=Name(id='sin', ctx=Load()), args=[ Name(id='a', ctx=Load())]), conversion=-1, format_spec=JoinedStr( values=[ Constant(value='.3')]))]))
- class ast.TemplateStr(values, /)¶
在 3.14 版本加入。
表示模板字串字面值的節點,由一系列
Interpolation
和Constant
節點組成。這些節點可以按任何順序排列,並且不必交錯。>>> 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
是一個整數其含義與
FormattedValue.conversion
相同。format_spec
是一個JoinedStr
節點,表示值的格式,如果未指定格式,則為None
。conversion
和format_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)¶
一個字典。
keys
和values
分別包含表示鍵和值的節點列表,順序匹配(即呼叫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
節點。當構建帶*args
的Call
節點時,必須使用此型別。>>> print(ast.dump(ast.parse('a, *b = it'), indent=4)) Module( body=[ Assign( targets=[ Tuple( elts=[ Name(id='a', ctx=Store()), Starred( value=Name(id='b', ctx=Store()), ctx=Store())], ctx=Store())], value=Name(id='it', ctx=Load()))])
表示式¶
- 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¶
一元運算子標記。
Not
是not
關鍵字,Invert
是~
運算子。>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4)) Expression( body=UnaryOp( op=Not(), operand=Name(id='x', ctx=Load())))
- class ast.BinOp(left, op, right)¶
二元操作(如加法或除法)。
op
是運算子,left
和right
是任意表達式節點。>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4)) Expression( body=BinOp( left=Name(id='x', ctx=Load()), op=Add(), right=Name(id='y', ctx=Load())))
- class ast.Add¶
- class ast.Sub¶
- class ast.Mult¶
- class ast.Div¶
- class ast.FloorDiv¶
- class ast.Mod¶
- class ast.Pow¶
- class ast.LShift¶
- class ast.RShift¶
- class ast.BitOr¶
- class ast.BitXor¶
- class ast.BitAnd¶
- class ast.MatMult¶
二元運算子標記。
- class ast.BoolOp(op, values)¶
布林運算,“or” 或 “and”。
op
是Or
或And
。values
是所涉及的值。具有相同運算子的連續操作,如a or b or c
,會被合併為一個具有多個值的節點。這不包括
not
,它是一個UnaryOp
。>>> print(ast.dump(ast.parse('x or y', mode='eval'), indent=4)) Expression( body=BoolOp( op=Or(), values=[ Name(id='x', ctx=Load()), Name(id='y', ctx=Load())]))
- class ast.Compare(left, ops, comparators)¶
兩個或多個值的比較。
left
是比較中的第一個值,ops
是運算子列表,comparators
是比較中第一個元素之後的值列表。>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4)) Expression( body=Compare( left=Constant(value=1), ops=[ LtE(), Lt()], comparators=[ Name(id='a', ctx=Load()), Constant(value=10)]))
- class ast.Eq¶
- class ast.NotEq¶
- class ast.Lt¶
- class ast.LtE¶
- class ast.Gt¶
- class ast.GtE¶
- class ast.Is¶
- class ast.IsNot¶
- class ast.In¶
- class ast.NotIn¶
比較運算子標記。
- class ast.Call(func, args, keywords)¶
函式呼叫。
func
是函式,通常是Name
或Attribute
物件。關於引數:args
包含按位置傳遞的引數列表。keywords
包含一個keyword
物件列表,表示按關鍵字傳遞的引數。
args
和keywords
引數是可選的,預設為空列表。>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4)) Expression( body=Call( func=Name(id='func', ctx=Load()), args=[ Name(id='a', ctx=Load()), Starred( value=Name(id='d', ctx=Load()), ctx=Load())], keywords=[ keyword( arg='b', value=Name(id='c', ctx=Load())), keyword( value=Name(id='e', ctx=Load()))]))
- class ast.keyword(arg, value)¶
函式呼叫或類定義中的關鍵字引數。
arg
是引數名的原始字串,value
是要傳入的節點。
- class ast.IfExp(test, body, orelse)¶
一個類似
a if b else c
的表示式。每個欄位都包含一個單獨的節點,所以在下面的例子中,三個都是Name
節點。>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4)) Expression( body=IfExp( test=Name(id='b', ctx=Load()), body=Name(id='a', ctx=Load()), orelse=Name(id='c', ctx=Load())))
- class ast.Attribute(value, attr, ctx)¶
屬性訪問,例如
d.keys
。value
是一個節點,通常是Name
。attr
是一個給出屬性名稱的裸字串,ctx
根據對屬性的操作是Load
、Store
還是Del
。>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4)) Expression( body=Attribute( value=Name(id='snake', ctx=Load()), attr='colour', ctx=Load()))
- class ast.NamedExpr(target, value)¶
一個命名錶達式。這個 AST 節點由賦值表示式運算子(也稱為海象運算子)產生。與
Assign
節點中的第一個引數可以是多個節點不同,在這裡target
和value
都必須是單個節點。>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4)) Expression( body=NamedExpr( target=Name(id='x', ctx=Store()), value=Constant(value=4)))
在 3.8 版本加入。
下標¶
- class ast.Subscript(value, slice, ctx)¶
下標,例如
l[1]
。value
是被下標的物件(通常是序列或對映)。slice
是一個索引、切片或鍵。它可以是Tuple
並且包含一個Slice
。ctx
根據對下標執行的操作是Load
、Store
還是Del
。>>> print(ast.dump(ast.parse('l[1:2, 3]', mode='eval'), indent=4)) Expression( body=Subscript( value=Name(id='l', ctx=Load()), slice=Tuple( elts=[ Slice( lower=Constant(value=1), upper=Constant(value=2)), Constant(value=3)], ctx=Load()), ctx=Load()))
- class ast.Slice(lower, upper, step)¶
常規切片(形式為
lower:upper
或lower:upper:step
)。只能出現在Subscript
的 slice 欄位中,可以直接出現,也可以作為Tuple
的元素出現。>>> print(ast.dump(ast.parse('l[1:2]', mode='eval'), indent=4)) Expression( body=Subscript( value=Name(id='l', ctx=Load()), slice=Slice( lower=Constant(value=1), upper=Constant(value=2)), ctx=Load()))
推導式¶
- class ast.ListComp(elt, generators)¶
- class ast.SetComp(elt, generators)¶
- class ast.GeneratorExp(elt, generators)¶
- class ast.DictComp(key, value, generators)¶
列表和集合推導式、生成器表示式以及字典推導式。
elt
(或key
和value
)是表示將對每個項進行求值的部分的單個節點。generators
是一個comprehension
節點列表。>>> print(ast.dump( ... ast.parse('[x for x in numbers]', mode='eval'), ... indent=4, ... )) Expression( body=ListComp( elt=Name(id='x', ctx=Load()), generators=[ comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), 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
是用於每個元素的引用 - 通常是Name
或Tuple
節點。iter
是要迭代的物件。ifs
是一個測試表達式列表:每個for
子句可以有多個ifs
。is_async
表示一個推導式是非同步的(使用async for
而不是for
)。該值為整數(0 或 1)。>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'), ... indent=4)) # Multiple comprehensions in one. Expression( body=ListComp( elt=Call( func=Name(id='ord', ctx=Load()), args=[ Name(id='c', ctx=Load())]), 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
中放入Tuple
或List
來表示。- type_comment¶
type_comment
是一個可選字串,帶有作為註釋的型別註解。
>>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # Multiple assignment Module( body=[ Assign( targets=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], value=Constant(value=1))]) >>> 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
是一個單獨的節點,可以是Name
、Attribute
或Subscript
。annotation
是註解,例如Constant
或Name
節點。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
是一個代表x
的Name
節點(帶有Store
上下文),op
是Add
,value
是一個值為 1 的Constant
。target
屬性不能是Tuple
或List
類的,這與Assign
的目標不同。>>> print(ast.dump(ast.parse('x += 2'), indent=4)) Module( body=[ AugAssign( target=Name(id='x', ctx=Store()), op=Add(), value=Constant(value=2))])
- class ast.Raise(exc, cause)¶
一個
raise
語句。exc
是要引發的異常物件,通常是Call
或Name
,對於獨立的raise
則為None
。cause
是raise x from y
中y
的可選部分。>>> print(ast.dump(ast.parse('raise x from y'), indent=4)) Module( body=[ Raise( exc=Name(id='x', ctx=Load()), cause=Name(id='y', ctx=Load()))])
- 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
是一個節點列表,例如Name
、Attribute
或Subscript
節點。>>> print(ast.dump(ast.parse('del x,y,z'), indent=4)) Module( body=[ Delete( targets=[ Name(id='x', ctx=Del()), Name(id='y', ctx=Del()), Name(id='z', ctx=Del())])])
- 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 y
。module
是 'from' 名稱的原始字串,不帶任何前導點號,對於from . import foo
這樣的語句則為None
。level
是一個整數,表示相對匯入的級別(0 表示絕對匯入)。>>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4)) Module( body=[ ImportFrom( module='y', names=[ alias(name='x'), alias(name='y'), alias(name='z')], level=0)])
- 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
節點。body
和orelse
各自包含一個節點列表。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
,Attribute
或Subscript
節點。iter
包含要迴圈的項,也是一個單個節點。body
和orelse
包含要執行的節點列表。如果迴圈正常結束,而不是透過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¶
break
和continue
語句。>>> print(ast.dump(ast.parse("""\ ... for a in b: ... if a > 5: ... break ... else: ... continue ... ... """), indent=4)) Module( body=[ For( target=Name(id='a', ctx=Store()), iter=Name(id='b', ctx=Load()), body=[ If( test=Compare( left=Name(id='a', ctx=Load()), ops=[ Gt()], comparators=[ Constant(value=5)]), body=[ Break()], orelse=[ Continue()])])])
- 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
部分則為None
。body
是一個節點列表。>>> print(ast.dump(ast.parse("""\ ... try: ... a + 1 ... except TypeError: ... pass ... """), indent=4)) Module( body=[ Try( body=[ Expr( value=BinOp( left=Name(id='a', ctx=Load()), op=Add(), right=Constant(value=1)))], handlers=[ ExceptHandler( type=Name(id='TypeError', ctx=Load()), body=[ Pass()])])])
- class ast.With(items, body, type_comment)¶
一個
with
塊。items
是一個withitem
節點的列表,代表上下文管理器,而body
是上下文內部的縮排塊。- type_comment¶
type_comment
是一個可選字串,帶有作為註釋的型別註解。
- class ast.withitem(context_expr, optional_vars)¶
with
塊中的單個上下文管理器。context_expr
是上下文管理器,通常是一個Call
節點。optional_vars
是as foo
部分的Name
、Tuple
或List
節點,如果未使用該部分則為None
。>>> print(ast.dump(ast.parse("""\ ... with a as b, c as d: ... something(b, d) ... """), indent=4)) Module( body=[ With( items=[ withitem( context_expr=Name(id='a', ctx=Load()), optional_vars=Name(id='b', ctx=Store())), withitem( context_expr=Name(id='c', ctx=Load()), optional_vars=Name(id='d', ctx=Store()))], body=[ Expr( value=Call( func=Name(id='something', ctx=Load()), args=[ Name(id='b', ctx=Load()), Name(id='d', ctx=Load())]))])])
模式匹配¶
- 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
是要進行比較的單例物件:None
、True
或False
。如果匹配主體是給定的常量,則此模式匹配成功。>>> 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
屬性包含將要繫結的名稱。如果name
為None
,則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.TypeVar
。name
是型別變數的名稱。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.ParamSpec
。name
是引數規範的名稱。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.TypeVarTuple
。name
是型別變數元組的名稱。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)¶
函式的引數。
- 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)¶
一個
yield
或yield 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)¶
global
和nonlocal
語句。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
是顯式指定的基類的節點列表。keywords
是keyword
節點的列表,主要用於‘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
上下文管理器。它們的欄位分別與For
和With
相同。僅在AsyncFunctionDef
的主體中有效。
備註
當字串由 ast.parse()
解析時,返回樹上的運算子節點(ast.operator
, ast.unaryop
, ast.cmpop
, ast.boolop
和 ast.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 <= 0
,FLAGS_VALUE
是ast.PyCF_ONLY_AST
,否則是ast.PyCF_OPTIMIZED_AST
。如果給出
type_comments=True
,解析器將被修改以檢查並返回 PEP 484 和 PEP 526 指定的型別註釋。這相當於將ast.PyCF_TYPE_COMMENTS
新增到傳遞給compile()
的標誌中。這將報告錯位型別註釋的語法錯誤。沒有此標誌,型別註釋將被忽略,並且所選 AST 節點上的type_comment
欄位將始終為None
。此外,# type: ignore
註釋的位置將作為Module
的type_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_comments
、mode='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 字面值結構:字串、位元組串、數字、元組、列表、字典、集合、布林值、
None
和Ellipsis
。這可以用於求值包含 Python 值的字串,而無需自己解析這些值。它不能求值任意複雜的表示式,例如涉及運算子或索引的表示式。
過去,該函式曾被記錄為“安全的”,但沒有定義這意味著什麼。這是誤導性的。這個函式被專門設計為不執行 Python 程式碼,與更通用的
eval()
不同。它沒有名稱空間、沒有名稱查詢,也沒有呼叫外部函式的能力。但它並非不受攻擊:一個相對較小的輸入可能導致記憶體耗盡或 C 棧耗盡,從而使程序崩潰。對於某些輸入,還可能存在過度的 CPU 消耗拒絕服務攻擊。因此,不建議在不受信任的資料上呼叫它。警告
由於 Python 的 AST 編譯器存在棧深度限制,可能會導致 Python 直譯器崩潰。
根據格式錯誤的輸入,它可能引發
ValueError
,TypeError
,SyntaxError
,MemoryError
和RecursionError
。在 3.2 版本發生變更: 現在允許位元組串和集合字面值。
在 3.9 版本發生變更: 現在支援使用
'set()'
建立空集合。在 3.10 版本發生變更: 對於字串輸入,現在會去除前導的空格和製表符。
- ast.get_docstring(node, clean=True)¶
返回給定 node(必須是
FunctionDef
、AsyncFunctionDef
、ClassDef
或Module
節點)的文件字串,如果它沒有文件字串,則返回None
。如果 clean 為 true,則使用inspect.cleandoc()
清理文件字串的縮排。在 3.5 版本發生變更: 現在支援
AsyncFunctionDef
。
- ast.get_source_segment(source, node, *, padded=False)¶
獲取生成 node 的 source 的原始碼片段。如果缺少某些位置資訊(
lineno
,end_lineno
,col_offset
或end_col_offset
),則返回None
。如果 padded 為
True
,多行語句的第一行將用空格填充以匹配其原始位置。在 3.8 版本加入。
- ast.fix_missing_locations(node)¶
當你用
compile()
編譯一個節點樹時,編譯器期望每個支援它們的節點都有lineno
和col_offset
屬性。為生成的節點填寫這些屬性相當繁瑣,所以這個輔助函式會遞迴地新增這些屬性,如果它們尚未設定,透過將它們設定為父節點的值。它從 node 開始遞迴工作。
- ast.increment_lineno(node, n=1)¶
將樹中從 node 開始的每個節點的行號和結束行號增加 n。這對於將“程式碼移動”到檔案中的不同位置很有用。
- ast.copy_location(new_node, old_node)¶
如果可能,將源位置(
lineno
,col_offset
,end_lineno
和end_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¶
啟用對頂層
await
、async for
、async with
和非同步推導式的支援。在 3.8 版本加入。
- ast.PyCF_ONLY_AST¶
生成並返回一個抽象語法樹,而不是返回一個編譯後的程式碼物件。
- ast.PyCF_OPTIMIZED_AST¶
返回的 AST 將根據
compile()
或ast.parse()
中的 optimize 引數進行最佳化。在 3.13 版本加入。
- ast.PyCF_TYPE_COMMENTS¶
啟用對 PEP 484 和 PEP 526 風格型別註釋(
# type: <type>
,# type: ignore <stuff>
)的支援。在 3.8 版本加入。
- ast.compare(a, b, /, *, compare_attributes=False)¶
遞迴地比較兩個 AST。
compare_attributes 影響 AST 屬性是否在比較中被考慮。如果 compare_attributes 為
False
(預設值),則屬性被忽略。否則它們必須全部相等。這個選項對於檢查 AST 是否在結構上相等,但在空格或類似細節上有所不同很有用。屬性包括行號和列偏移。在 3.14 版本加入。
命令列用法¶
在 3.9 版本中新增。
ast
模組可以作為指令碼從命令列執行。用法很簡單
python -m ast [-m <mode>] [-a] [infile]
接受以下選項
- -h, --help¶
顯示幫助資訊並退出。
- --no-type-comments¶
不解析型別註釋。
- -a, --include-attributes¶
包括行號和列偏移等屬性。
- --feature-version <version>¶
Python 版本,格式為 3.x(例如,3.10)。預設為直譯器的當前版本。
在 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 檔案中的多個語法錯誤。