有沒有人有一個簡單的例子,使用ast.NodeVisitor來遍歷Python 2.6中的抽象語法樹?訪問和generic_visit之間的區別並不清楚,我找不到任何使用谷歌codesearch或谷歌簡單的例子。如何使用ast.NodeVisitor的簡單示例?
回答
ast.visit
- 除非你覆蓋它的一個子類,當然 - 所謂的參觀foo
類的ast.Node
時,調用self.visit_foo
如果該方法存在,否則self.generic_visit
。後者在其實施ast
本身時也只是在每個子節點上調用self.visit
(並且不執行其他操作)。
因此,可以考慮,例如:
>>> class v(ast.NodeVisitor):
... def generic_visit(self, node):
... print type(node).__name__
... ast.NodeVisitor.generic_visit(self, node)
...
在這裏,我們覆蓋generic_visit
打印類名,但也調用到基類(使所有兒童也將參觀)。因此,例如...:
>>> 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
但假設我們不關心負荷節點(與兒童及其 - 如果他們有任何;-)。然後,一個簡單的方法來處理,可能是,如:
>>> class w(v):
... def visit_Load(self, node): pass
...
現在,當我們訪問一個負載節點,visit
調度,而不是generic_visit
了,而是我們的新visit_Load
......這沒有按」不要做任何事情。因此:
>>> y = w()
>>> y.visit(t)
Module
AugAssign
Subscript
Name
Index
Name
Store
Add
Subscript
Name
Index
Tuple
Name
Name
或者,假設我們也希望看到名稱節點的實際名稱;然後...:
>>> 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
更多,而是...:
>>> 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
覆蓋的 - 通常情況下,你只關心在幾種節點中,就像我們在Module和Name中這樣,所以我們可以覆蓋visit_Module
和visit_Name
,並讓ast的visit
代表我們進行調度。
generic_visit
在無法找到自定義訪問者(即visit_Name)時被調用。以下是我最近使用ast.NodeVisitor編寫的一段代碼:https://github.com/pypy/pypy/blob/master/py/_code/_assertionnew.py它解釋AST節點以獲取有關其中一些節點的調試信息,並在沒有提供特殊實現時使用generic_visit
。
查看ast.py中的代碼,複製粘貼並滾動您自己的步行者並不難。例如。
import ast
def str_node(node):
if isinstance(node, ast.AST):
fields = [(name, str_node(val)) for name, val in ast.iter_fields(node) if name not in ('left', 'right')]
rv = '%s(%s' % (node.__class__.__name__, ', '.join('%s=%s' % field for field in fields))
return rv + ')'
else:
return repr(node)
def ast_visit(node, level=0):
print(' ' * level + str_node(node))
for field, value in ast.iter_fields(node):
if isinstance(value, list):
for item in value:
if isinstance(item, ast.AST):
ast_visit(item, level=level+1)
elif isinstance(value, ast.AST):
ast_visit(value, level=level+1)
ast_visit(ast.parse('a + b'))
打印出
Module(body=[<_ast.Expr object at 0x02808510>])
Expr(value=BinOp(op=Add()))
BinOp(op=Add())
Name(id='a', ctx=Load())
Load()
Add()
Name(id='b', ctx=Load())
Load()
- 1. 簡單的示例如何使用Tao.Framework
- 2. 簡單IEnumerator使用(使用示例)
- 3. 簡單單例EJB示例
- 4. SilverStripe - 會話使用的簡單示例
- 5. 使用__setstate__和__getstate__的簡單示例
- 6. 使用SharedPreferences的簡單示例
- 7. 尋找簡單實用的C++示例如何使用ICU
- 8. 如何使用簡單的HttpGET-CRUD-NodeJS示例?
- 9. 關於如何使用Undo Monad Transformer的簡單示例
- 10. ReactiveSwift簡單示例
- 11. NSBrowser簡單示例
- 12. 簡單Silverlight示例
- 13. MKAnnotation,簡單示例
- 14. SocketAsyncEventArgs? - 簡單示例
- 15. NSXMLParser簡單示例
- 16. 簡單示例SwingUtilities
- 17. WebApplicationInitializer簡單示例
- 18. 如何使用這個單例示例
- 19. 如何使用jQuery qTip - 簡單示例請
- 20. Guice Servlets的簡單示例
- 21. 簡單的GoLang SSL示例
- 22. SenchaTouch的簡單JSON示例
- 23. 簡單的MediaElement類示例
- 24. 簡單的Java OAuth示例
- 25. 簡單的C++ hash_set示例
- 26. 簡單的sqlite示例?
- 27. 簡單的GWT OpenID示例
- 28. 簡單的Android RecyclerView示例
- 29. 模板的簡單示例
- 30. 簡單的ASP.NET MVC示例
謝謝! - 這正是我所期待的。 – lacker 2009-10-04 02:29:03
@lacker,不客氣! – 2009-10-04 02:56:05
太好了,我想了解更多的編譯器。現在的答案是什麼... – 2015-06-25 10:33:17