如何使用ast.NodeVisitor的简单示例? [英] Simple example of how to use ast.NodeVisitor?

查看:193
本文介绍了如何使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆