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

2024-07-04

有谁有一个使用 ast.NodeVisitor 来遍历 Python 2.6 中的抽象语法树的简单示例吗?我不清楚访问和 generic_visit 之间的区别,而且我找不到任何使用谷歌代码搜索或普通谷歌的示例。


ast.visit——当然,除非你在子类中重写它——当被调用来访问一个ast.Node班级的foo, calls 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打印类名,但是also调用基类(这样所有的孩子也会被访问)。例如...:

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

emits:

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

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

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

现在当我们访问 Load 节点时,visit派遣,而不是generic_visit不再多了,但是对于我们的新visit_Load...根本没有做任何事情。所以:

>>> y = w()
>>> y.visit(t)
Module
AugAssign
Subscript
Name
Index
Name
Store
Add
Subscript
Name
Index
Tuple
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-- 通常,您只对几种节点感兴趣,就像我们在模块和名称中一样,因此我们可以覆盖visit_Module and visit_Name让 astvisit代表我们进行调度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用ast.NodeVisitor的简单示例? 的相关文章

随机推荐