gpt4 book ai didi

python - 如何使用 ast.NodeVisitor 的简单示例?

转载 作者:IT老高 更新时间:2023-10-28 21:32:30 26 4
gpt4 key购买 nike

有没有人有一个使用 ast.NodeVisitor 在 Python 2.6 中遍历抽象语法树的简单示例?我不清楚 visit 和 generic_visit 之间的区别,我找不到任何使用 google codesearch 或普通 google 的示例。

最佳答案

ast.visit -- 除非你在子类中重写它,当然 -- 当被调用访问类 fooast.Node code>,如果该方法存在则调用 self.visit_foo,否则调用 self.generic_visit。后者,同样在 ast 类本身的实现中,只是在每个子节点上调用 self.visit(并且不执行其他操作)。

所以,考虑一下,例如:

>>> class v(ast.NodeVisitor):
... def generic_visit(self, node):
... print type(node).__name__
... ast.NodeVisitor.generic_visit(self, node)
...

在这里,我们重写了 generic_visit 以打印类名,但调用了基类(这样所有子类也将被访问)。比如……:

>>> x = v()
>>> t = ast.parse('d[x] += v[y, x]')
>>> x.visit(t)

发射:

Module
AugAssign
Subscript
Name
Load
Index
Name
Load
Store
Add
Subscript
Name
Load
Index
Tuple
Name
Load
Name
Load
Load
Load

但是假设我们不关心 Load 节点(及其子节点——如果它们有的话;-)。那么一个简单的处理方法可能是,例如:

>>> class w(v):
... def visit_Load(self, node): pass
...

现在,当我们访问 Load 节点时,visit 分派(dispatch),不再是 generic_visit,而是我们新的 visit_Load.. . 这根本没有做任何事情。所以:

>>> y = w()
>>> y.visit(t)
Module
AugAssign
Subscript
Name
Index
Name
Store
Add
Subscript
Name
Index
Tuple
Name
Name

或者,假设我们还想查看 Name 节点的实际名称;然后...:

>>> class z(v):
... def visit_Name(self, node): print 'Name:', node.id
...
>>> z().visit(t)
Module
AugAssign
Subscript
Name: d
Index
Name: x
Store
Add
Subscript
Name: v
Index
Tuple
Name: y
Name: x
Load
Load

但是,NodeVisitor 是一个类,因为它可以在访问期间存储信息。假设我们想要的只是“模块”中的一组名称。那么我们就不需要再重写generic_visit了,而是……:

>>> class allnames(ast.NodeVisitor):
... def visit_Module(self, node):
... self.names = set()
... self.generic_visit(node)
... print sorted(self.names)
... def visit_Name(self, node):
... self.names.add(node.id)
...
>>> allnames().visit(t)
['d', 'v', 'x', 'y']

这种事情比需要覆盖 generic_visit 的用例更典型——通常,您只对几种节点感兴趣,就像我们在 Module 和 Name 中一样,所以我们可以重写 visit_Modulevisit_Name 并让 ast 的 visit 代表我们进行调度。

关于python - 如何使用 ast.NodeVisitor 的简单示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1515357/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com