使用AST模块来改变和删除赋值/函数调用

时间:2018-02-13 16:12:39

标签: python abstract-syntax-tree mutation

例如,如果我想要更改大于小于或等于我已成功执行:

def visit_Gt(self, node):
    new_node = ast.GtE()
    return ast.copy_location(new_node, node)

我如何访问/检测赋值操作(=)和函数调用()并简单地删除它们?我正在阅读AST文档,我找不到访问赋值或函数调用类的方法,然后什么都不返回。

我正在寻求分配操作的一个例子:

print("Start")
x = 5
print("End")

变为:

print("Start")

print("End")

我正在寻找删除函数调用的一个例子:

 print("Start")
 my_function_call(Args)
 print("End")

变为

print("Start")

print("End")

1 个答案:

答案 0 :(得分:2)

您可以使用ast.NodeTransformer() subclass来改变现有的AST树:

import ast

class RemoveAssignments(ast.NodeTransformer):
    def visit_Assign(self, node):
        return None

    def visit_AugAssign(self, node):
        return None

new_tree = RemoveAssignments().visit(old_tree)

上面的类删除None以从输入树中完全删除节点。 AssignAugAssign节点包含整个赋值语句,因此生成结果的表达式和目标列表(将结果分配给1个或多个名称)。

这意味着以上将转为

print('Start!')
foo = 'bar'
foo += 'eggs'
print('Done!')

print('Start!')


print('Done!')

如果您需要做出更细粒度的决策,请直接查看赋值的子节点,或者将子节点传递给self.visit()以使变换器进一步调用visit_*挂钩对于他们,如果他们存在:

class RemoveFunctionCallAssignments(NodeTransformer):
    """Remove assignments of the form "target = name()", so a single name being called

    The target list size plays no role.

    """
    def visit_Assign(self, node):
        if isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name):
            return None
        return node

这里,如果赋值的值侧(右侧的表达式)是应用于直接{{1}的None节点,我们只返回Call }节点。返回传入的原始节点对象意味着它不会被替换。

要替换顶级函数调用(那些没有赋值或其他表达式的函数),请查看Name个节点;这些是表达式语句,而不仅仅是某些其他构造的表达式。如果您的Expr节点带有Expr,则可以将其删除:

Call

另请参阅优秀的Green Tree Snakes documentationcovers working on the AST tree以及更多示例。