2011-05-15 60 views
3

我正在使用Python 2.6.5。Python AST:如何獲得節點的子節點

給定一個抽象語法樹,我想獲取它的子元素。

我搜索堆棧溢出,但無濟於事。大部分帖子都在ast.NodeVisitor以及其中定義的方法visit,generic_visit()。 然而AFAIU,visit()generic_visit()不給我們的孩子們,而他們直接遞歸應用的功能對他們

可有人請寫一個簡短的代碼或者這樣來證明呢? 在Python庫中是否存在相同的預定義函數?

謝謝!

回答

3

包含節點子節點的attaributes取決於節點表示的語法類型。每個節點類還有一個特殊的_fields屬性,該屬性列出了該類所具有的子節點的屬性名稱。例如,

>>> 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> 

等等。

編輯,澄清這是怎麼回事

想要進一步瞭解,請在CPython Abstract Grammar

一目瞭然考慮:

>>> type(ast.parse('5+a')) 
<class '_ast.Module'> 

事實上,如果你看一下語法,第一條生產規則是針對模塊。它似乎需要一系列的聲明,作爲一個稱爲body的參數。

>>> ast.parse('5+a')._fields 
('body',) 
>>> ast.parse('5+a').body 
[<_ast.Expr object at 0x02E965B0>] 

的AST的_fields屬性僅僅是「體」,並且身體屬性是AST節點序列。回到語法,尋找在stmt生產規則,我們看到Expr接受一個EXPR,命名爲value

>>> ast.parse('5+a').body[0].value 
<_ast.BinOp object at 0x02E96330> 

如果我們仰望的BinOp的定義,我們可以看到,它需要3個不同的參數,左,操作和權利。我希望你應該能夠從那裏出發。

+0

感謝您的回覆!不過,我還沒有正確理解它......所以node._fields會給那個特定節點的孩子? (以tupple的形式?)....那麼身體和價值是什麼意思?謝謝你的幫助! – Adwaitvedant 2011-05-16 05:37:11

3

ast模塊提供了一個iter_child_nodes函數,您可能會發現它很有用。

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             

                       ` 
相關問題