baa*_*ezx 4 python stack abstract-syntax-tree tree-traversal
使用什么类型的树遍历ast(特别是ast.NodeVisitor())?当我创建一个堆栈并将遍历的每个节点推入堆栈时,结果似乎是“广度优先”树遍历。这意味着顺序取决于树中的级别。
前任。树看起来像
Module
Assign
Name
Store
Call
Attribute
Str
Load
Run Code Online (Sandbox Code Playgroud)
堆栈看起来像
[Module,Assign,Name,Call,Store,Attribute,Str,Load]
Run Code Online (Sandbox Code Playgroud)
前任。代码
stack = []
class a(ast.NodeTransformer):
def visit_Num(self,node):
stack.append(node)
...
return node
... #this is all the other visit_*() functions
def visit_Str(self,node):
stack.append(node)
...
return node
if __name__ == "__main__":
with open('some_file.py','r') as pt:
tree = ast.parse(pt)
new_tree = a()
new_tree_edit = ast.fix_missing_locations(new_tree.visit(tree)) # I have tried with and without calling fix_missing_locations and got the same results.
print stack
Run Code Online (Sandbox Code Playgroud)
该ast.walk()函数遍历树呼吸第一; 见ast.py来源:
def walk(node):
"""
Recursively yield all descendant nodes in the tree starting at *node*
(including *node* itself), in no specified order. This is useful if you
only want to modify nodes in place and don't care about the context.
"""
from collections import deque
todo = deque([node])
while todo:
node = todo.popleft()
todo.extend(iter_child_nodes(node))
yield node
Run Code Online (Sandbox Code Playgroud)
新节点被推入队列,下一个被遍历的节点是队列的前端。
如果您想要深度优先遍历,请改用 of 的子类ast.NodeVisitor();它将使用递归遍历树;NodeVisitor.visit()电话NodeVisitor.generic_visit(),除非更多的节点特定访问者方法被定义,并NodeVisitor.generic_visit()呼吁NodeVisitor.visit()再次子节点:
class NodeVisitor(object):
"""
A node visitor base class that walks the abstract syntax tree and calls a
visitor function for every node found. This function may return a value
which is forwarded by the `visit` method.
This class is meant to be subclassed, with the subclass adding visitor
methods.
Per default the visitor functions for the nodes are ``'visit_'`` +
class name of the node. So a `TryFinally` node visit function would
be `visit_TryFinally`. This behavior can be changed by overriding
the `visit` method. If no visitor function exists for a node
(return value `None`) the `generic_visit` visitor is used instead.
Don't use the `NodeVisitor` if you want to apply changes to nodes during
traversing. For this a special visitor exists (`NodeTransformer`) that
allows modifications.
"""
def visit(self, node):
"""Visit a node."""
method = 'visit_' + node.__class__.__name__
visitor = getattr(self, method, self.generic_visit)
return visitor(node)
def generic_visit(self, node):
"""Called if no explicit visitor function exists for a node."""
for field, value in iter_fields(node):
if isinstance(value, list):
for item in value:
if isinstance(item, AST):
self.visit(item)
elif isinstance(value, AST):
self.visit(value)
Run Code Online (Sandbox Code Playgroud)
如果您执行子类化NodeVisitor(或者它的派生版本NodeTransformer),请记住还要调用super(YourClass, self).generic_visit(node)您的特定visit_*方法以继续遍历树。
| 归档时间: |
|
| 查看次数: |
3321 次 |
| 最近记录: |