遍歷語法樹獲取資訊:
語法樹node
for node in ast.walk(tree):
if isinstance(node, ast.functiondef):
print(node.name)
class codevisitor(ast.nodevisitor):
def generic_visit(self, node):
print type(node).__name__
ast.nodevisitor.generic_visit(self, node)
def visit_functiondef(self, node):
print type(node).__name__
ast.nodevisitor.generic_visit(self, node)
def visit_assign(self, node):
print type(node).__name__
ast.nodevisitor.generic_visit(self, node)
當visit_***這個方法存在時,呼叫self.visit_***方法訪問ast.node中的***型別結點
否則的話,呼叫self.generic_visit
generic_visit :ast類中實現,呼叫self.visit訪問子結點
具體應用
with open(
'func_def.py','r'
) as f:
content=f.read(
)t=ast.parse(content)
1、列印抽象語法樹
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結點
ast_visitor(t)
2、列印ast所有結點的型別
class v(ast.nodevisitor):
def generic_visit(self, node):
print(type(node).__name__)
ast.nodevisitor.generic_visit(self,node)
x = v(
)x.visit(t)
module
functiondef
arguments
argarg
assign
name
store
binop
name
load
addname
load
return
name
load
functiondef
arguments
argarg
assign
name
store
binop
name
load
subname
load
return
name
load
ifcompare
name
load
eqconstant
expr
call
name
load
call
name
load
constant
constant
3、遍歷結點時跳過不想要的結點
例如:跳過load結點
class w(v):
def visit_load(self, node):
pass
y = w(
)y.visit(t)
module
functiondef
arguments
argarg
assign
name
store
binop
name
addname
return
name
functiondef
arguments
argarg
assign
name
store
binop
name
subname
return
name
ifcompare
name
eqconstant
expr
call
name
call
name
constant
constant
4、對某型別結點進行處理
例如:訪問name結點時具體列印name結點的id
class z(w):
def visit_name(self,node):
print(
"name:",node.id)
z = z(
)z.visit(t)
module
functiondef
arguments
argarg
assign
name: a
binop
name: x
addname: y
return
name: a
functiondef
arguments
argarg
assign
name: b
binop
name: x
subname: y
return
name: b
ifcompare
name: __name__
eqconstant
expr
call
name: print
call
name: add
constant
constant
5、遍歷語法樹過程中儲存資訊,對想要的結點override而不用修改generic_visit
例如:把所有name節點的id屬性放入set中
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=allnames(
)allnames.visit(t)
['__name__', 'a', 'add', 'b', 'print', 'x', 'y'
]
部分參考文件:
getting to and from ast|meet the nodes|working on the tree|examples of working on with asts
編譯抽象語法樹
編譯抽象語法樹 對大多數開發人員來說,編譯就意謂著產生本地 給人感覺就是乙個字,難。但是,並不一定要產生本地 對於 dsl,通常產生其他更加通用的程式語言。net 框架提供幾個把抽象語法樹編譯成程式的功能。技術的選擇取決於幾個因素。例如,如果語言針對的是開發人員,那麼,生成文字檔案就足夠了,內容可以...
python實現樹的遍歷
二叉樹的遍歷是指按照某種順序依次訪問樹中的所有節點一次。四種遍歷方式分別是 先序遍歷 中序遍歷 後序遍歷 層序遍歷。其中前三種屬於深度優先遍歷 dfs 後一種屬於廣度優先遍歷 bfs 首先宣告節點類 class treenode def init self,x self.val x self.lef...
python遍歷目錄樹
假定你希望對某個資料夾中的所有檔案改名,包括該資料夾中所有子資料夾中的所有檔案。也就是說,你希望遍歷目錄樹,處理遇到的每個檔案。寫程式完成這件事,可能需要一些技巧。好在,python 提供了乙個函式,替你處理這個過程。請看 c delicious 資料夾及其內容,如圖 9 1 所示。這裡有乙個例子程...