使用python ast.NodeTransformer修改多个节点

使用python ast.NodeTransformer修改多个节点,python,abstract-syntax-tree,Python,Abstract Syntax Tree,我有这样的输入源代码 def foo(my_input): return my_input + 42 def method_name(arg0): return my_input + 42 希望它像这样转变 def foo(my_input): return my_input + 42 def method_name(arg0): return my_input + 42 用于此目的的ast节点转换器是这样编写的 class MyRenamer(ast.NodeTrans

我有这样的输入源代码

def foo(my_input):
  return my_input + 42
def method_name(arg0):
  return my_input + 42
希望它像这样转变

def foo(my_input):
  return my_input + 42
def method_name(arg0):
  return my_input + 42
用于此目的的ast节点转换器是这样编写的

class MyRenamer(ast.NodeTransformer):

  def __init__(self):
    self._arg_count = 0

  def visit_FunctionDef(self, node):
    node.name = "method_name"
    return node

  def visit_arg(self, node):
    node.arg = "arg_{}".format(self._arg_count)
    self._arg_count += 1
    return node
node = ast.parse(code)
renamer = MyRenamer()
node2 = renamer.visit(node)
print(astor.to_source(node2))
但是当我这样调用上面的变压器时

class MyRenamer(ast.NodeTransformer):

  def __init__(self):
    self._arg_count = 0

  def visit_FunctionDef(self, node):
    node.name = "method_name"
    return node

  def visit_arg(self, node):
    node.arg = "arg_{}".format(self._arg_count)
    self._arg_count += 1
    return node
node = ast.parse(code)
renamer = MyRenamer()
node2 = renamer.visit(node)
print(astor.to_source(node2))
我得到的输出是

def method_name(my_input):
    return my_input + 42

此处函数的参数未更改。

访问者需要通过访问当前访问节点的所有子节点来遍历AST。该方法为您实现了这一点,但您必须在每次访问时调用它。。。方法,或者至少对于那些可能有孩子的人

import ast
import astor

class MyRenamer(ast.NodeTransformer):

  def __init__(self):
    self._arg_count = 0

  def visit_FunctionDef(self, node):
    node.name = "method_name"
    self.generic_visit(node)
    return node

  def visit_arg(self, node):
    node.arg = "arg_{}".format(self._arg_count)
    self._arg_count += 1
    self.generic_visit(node)
    return node

code = """
def foo(my_input):
  return my_input + 42
"""

node = ast.parse(code)
renamer = MyRenamer()
node2 = renamer.visit(node)
print(astor.to_source(node2))


这将提供您期望的输出,但在更大的上下文中,将所有函数重命名为“method_name”,这可能不是您想要的。函数体中仍然有可能需要重命名的标识符。

此转换会创建无效代码(def method_name(arg0):return my_input+42)。这是故意的吗?是的,我将来也会修改它。