英文:
How to compare two Python ASTs, ignoring arguments?
问题
我想要优雅地比较两个Python表达式,忽略参数中的任何差异。例如,比较plt.show()
和plt.show(*some-args)
应该返回True
。
我尝试使用ast
解析表达式,如下所示:
import ast
node1 = ast.parse("plt.show()").body[0]
node2 = ast.parse("plt.show(*some-args)").body[0]
print(node1 == node2)
返回:False
英文:
I want to elegantly compare two Python expressions ignoring any differences in the arguments. For example comparing plt.show()
and plt.show(*some-args)
should return True
.
I've tried parsing the expressions using ast
as follows:
import ast
node1 = ast.parse("plt.show()").body[0]
node2 = ast.parse("plt.show(*some-args)").body[0]
print(node1 == node2)
Returns: False
答案1
得分: 0
from itertools import zip_longest
from typing import Union
def compare_ast(node1: Union[ast.expr, list[ast.expr]], node2: Union[ast.expr, list[ast.expr]], ignore_args=False) -> bool:
"""比较两个 AST 节点是否相等。"""
if type(node1) is not type(node2):
return False
if isinstance(node1, ast.AST):
for k, v in vars(node1).items():
if k in {"lineno", "end_lineno", "col_offset", "end_col_offset", "ctx"}:
continue
if ignore_args and k == "args":
continue
if not compare_ast(v, getattr(node2, k), ignore_args):
return False
return True
elif isinstance(node1, list) and isinstance(node2, list):
return all(compare_ast(n1, n2, ignore_args) for n1, n2 in zip_longest(node1, node2))
else:
return node1 == node2
import ast
node1 = ast.parse("plt.show()").body[0]
node2 = ast.parse("plt.show(*some-args)").body[0]
print(compare_ast(node1, node2, ignore_args=True))
Returns: True
<details>
<summary>英文:</summary>
Some slight modifications to [@Seanny123's answer](https://stackoverflow.com/a/66733795/11080806):
```python
from itertools import zip_longest
from typing import Union
def compare_ast(node1: Union[ast.expr, list[ast.expr]], node2: Union[ast.expr, list[ast.expr]], ignore_args=False) -> bool:
"""Compare two AST nodes for equality."""
if type(node1) is not type(node2):
return False
if isinstance(node1, ast.AST):
for k, v in vars(node1).items():
if k in {"lineno", "end_lineno", "col_offset", "end_col_offset", "ctx"}:
continue
if ignore_args and k == "args":
continue
if not compare_ast(v, getattr(node2, k), ignore_args):
return False
return True
elif isinstance(node1, list) and isinstance(node2, list):
return all(compare_ast(n1, n2, ignore_args) for n1, n2 in zip_longest(node1, node2))
else:
return node1 == node2
Example:
import ast
node1 = ast.parse("plt.show()").body[0]
node2 = ast.parse("plt.show(*some-args)").body[0]
print(compare_ast(node1, node2, ignore_args=True))
Returns: True
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论