對於聲明節點,允許您返回新節點的列表。這可以讓您用多個替換單個語句。引用文檔:
對於作爲語句集合(適用於所有語句節點)的一部分的節點,訪問者也可以返回節點列表,而不僅僅是單個節點。
對於你的表情,有一個單一的頂級Expr()
表達式語句節點:
>>> ast.dump(ast.parse('f(g())'))
"Module(body=[Expr(value=Call(func=Name(id='f', ctx=Load()), args=[Call(func=Name(id='g', ctx=Load()), args=[], keywords=[])], keywords=[]))])"
>>> import ast
>>> ast.dump(ast.parse('f(g())'))
"Module(body=[Expr(value=Call(func=Name(id='f', ctx=Load()), args=[Call(func=Name(id='g', ctx=Load()), args=[], keywords=[])], keywords=[]))])"
因此,所有你需要做的就是提供一個visit_Expr
處理程序返回的2層語句的節點列表;第一個調用g()
的調用(Assign()
語句節點),第二個調用f
傳遞新的變量名稱(另一個Expr()
語句節點)。
我會保持變壓器子類中的狀態,當您進入和離開表達式語句上下文時設置標誌,並跟蹤該上下文下的調用棧。當你再回到visit_Expr
,你回你的新格局:
self._expr_statement = False
def visit_Expr(node):
self._expr_statement = True
self.generic_visit(node)
self._expr_statement = False
if <specific state on self matches expectations>:
tempvar = <generated_new_name>
return [
Assign([Name(tempvar, Store())], <inner_call>),
Expr(Call(
<outer_function_name_expr>,
args=[Name(tempvar, Load())],
keyword=[]))
]
else:
# no replacement takes place
return node
的NodeTransformer then uses that list of elements to replace the previous
Expr的()`節點。
請注意,您必須仍然調用self.generic_visit(node)
以確保仍然處理嵌套節點;然後將爲這些嵌套節點調用另外的visit_*
方法。這樣做使得在visit_Call
方法中,您可以檢查self._expr_statement
標誌,然後測試是否存在嵌套調用,然後在self
上存儲足夠的上下文以使visit_Expr()
方法返回。
請包括你沒有得到多個節點返回工作;包括你的嘗試,所以我可以幫助你* *。 *將多個節點作爲列表返回*明確支持*。 –