I am working on Python 2.6.5.
Given a Abstract Syntax Tree, I want to obtain its children.
Most StackOverflow posts discuss ast.NodeVisitor
and the methods defined in it: visit()
, generic_visit()
.
However, visit()
and generic_visit()
do not give the children, rather they directly apply the function recursively on them.
Can someone please write a s开发者_如何学Gohort code or so to demonstrate it? Does there exist a predefined function in python library for the same?
The attaributes containing the node's children depend on the type of syntax the node represents. Every node class also has a special _fields
attribute, that lists the attribute names for the child nodes that class has. For instance,
>>> ast.parse('5+a')
<_ast.Module object at 0x02C1F730>
>>> ast.parse('5+a').body
[<_ast.Expr object at 0x02C1FF50>]
>>> ast.parse('5+a').body[0]
<_ast.Expr object at 0x02C1FBF0>
>>> ast.parse('5+a').body[0]._fields
('value',)
>>> ast.parse('5+a').body[0].value
<_ast.BinOp object at 0x02C1FF90>
>>> ast.parse('5+a').body[0].value._fields
('left', 'op', 'right')
>>> ast.parse('5+a').body[0].value.left
<_ast.Num object at 0x02C1FB70>
and so on.
Edit, to clarify what's going on
Before going any further, take a glance at the CPython Abstract Grammar
Consider:
>>> type(ast.parse('5+a'))
<class '_ast.Module'>
In fact, if you look at the grammar, the first production rule is for Module. It appears to take a sequence of statements, as an argument called body.
>>> ast.parse('5+a')._fields
('body',)
>>> ast.parse('5+a').body
[<_ast.Expr object at 0x02E965B0>]
The _fields
attribute of the AST is just "body", and the body attribute is a sequence of AST nodes. Back to the grammar, looking in the production rules for stmt
, we see that Expr
takes a single expr, named value
>>> ast.parse('5+a').body[0].value
<_ast.BinOp object at 0x02E96330>
If we look up the definition for BinOp, we see that it takes 3 different arguments, left, op and right. You should be able to proceed from there, I hope.
The ast
module provides an iter_child_nodes
function you might find useful.
def iter_child_nodes(node):
"""
Yield all direct child nodes of *node*, that is, all fields that are nodes
and all items of fields that are lists of nodes.
"""
for name, field in iter_fields(node):
if isinstance(field, AST):
yield field
elif isinstance(field, list):
for item in field:
if isinstance(item, AST):
yield item
`
精彩评论