如何使用ast.NodeVisitor的简单示例? [英] Simple example of how to use ast.NodeVisitor?
问题描述
有人使用ast.NodeVisitor来在Python 2.6中使用抽象语法树的简单示例吗?对我来说,visit和generic_visit之间的区别尚不清楚,我无法找到使用Google Codesearch或纯Google的任何示例。
Does anyone have a simple example using ast.NodeVisitor to walk the abstract syntax tree in Python 2.6? The difference between visit and generic_visit is unclear to me, and I cannot find any example using google codesearch or plain google.
推荐答案
ast.visit
-当然,除非您在子类中覆盖了它-在调用 ast.Node
时被调用类 foo
的实例,如果存在该方法,则调用 self.visit_foo
,否则 self.generic_visit
。后者再次在类 ast
中的实现中,仅在每个子节点上调用 self.visit
(并执行
ast.visit
-- unless you override it in a subclass, of course -- when called to visit an ast.Node
of class foo
, calls self.visit_foo
if that method exists, otherwise self.generic_visit
. The latter, again in its implementation in class ast
itself, just calls self.visit
on every child node (and performs no other action).
因此,请考虑例如:
>>> class v(ast.NodeVisitor):
... def generic_visit(self, node):
... print type(node).__name__
... ast.NodeVisitor.generic_visit(self, node)
...
在这里,我们覆盖 generic_visit
打印类名,但还调用基类(这样也将访问所有子类)。因此,例如...:
Here, we're overriding generic_visit
to print the class name, but also calling up to the base class (so that all children will also be visited). So for example...:
>>> 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
但是假设我们不在乎加载节点(及其子节点-如果有的话;-)。那么,解决该问题的简单方法可能是:
But suppose we didn't care for Load nodes (and children thereof -- if they had any;-). Then a simple way to deal with that might be, e.g.:
>>> class w(v):
... def visit_Load(self, node): pass
...
现在,当我们访问加载节点时,访问
调度,而不是 generic_visit
但是,对于我们新的 visit_Load
...来说,它什么也没做。因此:
Now when we're visiting a Load node, visit
dispatches, NOT to generic_visit
any more, but to our new visit_Load
... which doesn't do anything at all. So:
>>> y = w()
>>> y.visit(t)
Module
AugAssign
Subscript
Name
Index
Name
Store
Add
Subscript
Name
Index
Tuple
Name
Name
或者,假设我们还想查看Name节点的实际名称;然后...:
or, suppose we also wanted to see the actual names for Name nodes; then...:
>>> 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
了,而是...:
But, NodeVisitor is a class because this lets it store information during a visit. Suppose all we want is the set of names in a "module". Then we don't need to override generic_visit
any more, but rather...:
>>> 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
和 visit_Name
并让ast 访问
代表我们进行调度。
This kind of thing is a more typical use case than ones requiring overrides of generic_visit
-- normally, you're only interested in a few kinds of nodes, like we are here in Module and Name, so we can just override visit_Module
and visit_Name
and let ast's visit
do the dispatching on our behalf.
这篇关于如何使用ast.NodeVisitor的简单示例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!