如何忽略参数差异比较两个Python AST?
解决Python表达式忽略参数差异的比较方法
要实现忽略参数差异的表达式比较,核心是自定义AST节点的比较逻辑,只校验函数调用的核心标识(比如plt.show这个函数本身),跳过参数部分的对比。以下是具体实现方案:
核心思路
Python的ast模块默认会严格对比节点的所有属性(包括参数列表),所以我们需要编写一个自定义比较函数,针对Call类型节点,只校验调用的函数是否一致,忽略args和keywords参数。
实现代码
import ast def compare_ignoring_args(node1, node2): # 先判断两个节点类型是否一致 if type(node1) != type(node2): return False # 如果是函数调用节点,只比较函数部分,忽略参数 if isinstance(node1, ast.Call): # 递归比较函数的标识(比如plt.show对应的Attribute节点) return compare_ignoring_args(node1.func, node2.func) # 如果是属性节点(比如plt.show中的show是attr,plt是value) if isinstance(node1, ast.Attribute): return (compare_ignoring_args(node1.value, node2.value) and node1.attr == node2.attr) # 如果是名称节点(比如直接调用foo()的foo) if isinstance(node1, ast.Name): return node1.id == node2.id # 其他类型节点(比如常量等)按默认逻辑比较 return ast.dump(node1) == ast.dump(node2) # 测试示例 node1 = ast.parse("plt.show()").body[0] node2 = ast.parse("plt.show(*some_args)").body[0] print(compare_ignoring_args(node1, node2)) # 输出: True # 更多测试场景 node3 = ast.parse("foo()").body[0] node4 = ast.parse("foo(1, bar='baz')").body[0] print(compare_ignoring_args(node3, node4)) # 输出: True node5 = ast.parse("plt.plot()").body[0] print(compare_ignoring_args(node1, node5)) # 输出: False(函数不同)
代码说明
- 递归处理AST节点:针对
Call节点,只对比其func属性(即被调用的函数),跳过参数列表; - 兼容不同函数标识:处理
Attribute(如plt.show)和Name(如foo)类型的函数节点,确保函数路径完全一致; - 基础类型回退:对于非函数调用的节点,用
ast.dump()的结果做默认对比,保证基础逻辑的正确性。
内容的提问来源于stack exchange,提问作者Jonathan Biemond
相关产品推荐
相关产品推荐

