Я играю с АСТ-манипуляциями. В настоящее время я пытаюсь удалить определенные узлы из ввода AST. Думаю, класс NodeTransformer является подходящим инструментом для этой цели. К сожалению, он не ведет себя так, как ожидалось.Python NodeTransformer: как удалить узлы?
documetation говорит:
«NodeTransformer будет ходить AST и использовать возвращаемое значение методов для посетителей, чтобы заменить или удалить старый узел Если возвращаемое значение метода посетителя не является ни один узел будет. удаляться из своего местоположения, в противном случае он заменяется возвращаемым значением ».
Теперь посмотрим на мою программу:
import _ast
import ast
import sys
#ast transformer
class MyTransformer(ast.NodeTransformer):
def iterate_children(self, node):
"""
helper
"""
children = ast.iter_child_nodes(node)
for c in children:
self.visit(c)
def generic_visit(self, node):
"""
default behaviour
"""
print("visiting: "+node.__class__.__name__)
self.iterate_children(node)
return node
def visit_For(self, node):
"""
For nodes: replace with nothing
"""
print("removing a For node")
return None
#read source program
filename = sys.argv[1]
with open (filename, "r") as myfile:
source = str(myfile.read())
#compile source to ast
m = compile(source, "<string>", "exec", _ast.PyCF_ONLY_AST)
#do ast manipulation
t = MyTransformer()
t.visit(m)
# fix locations
m = ast.fix_missing_locations(m)
#visualize the resulting ast
#p = AstPrinter()
#p.fromAst(m)
#execute the transformed program
print("computing...")
codeobj = compile(m, '<string>', 'exec')
exec(codeobj)
Здесь входной файл:
l = [0, 1, 2, 3]
total = 0
for i in l:
total += i
print(total)
И результат:
visiting: Module
visiting: Assign
visiting: Name
visiting: Store
visiting: List
visiting: Num
visiting: Num
visiting: Num
visiting: Num
visiting: Load
visiting: Assign
visiting: Name
visiting: Store
visiting: Num
removing a For node
visiting: Expr
visiting: Call
visiting: Name
visiting: Load
visiting: Name
visiting: Load
computing...
6
Я ожидал '0', потому что цикл был удален. Но есть «6» (= 0 + 1 + 2 + 3).
Кто-нибудь знает почему?
Python версии: 3.2.3
Числа в() указывают номер строки в программе ввода. Код рисунка изображения здесь не указан; пожалуйста, игнорируйте «корневой» узел. Как вы можете видеть, цикл For все еще существует.
Спасибо за чтение!
Update 21,8 .:
Я разместил ссылку на этот вопрос на питона ([email protected] рассылки). Похоже, я слишком много переписывал. Без посетителя для детей он работает так, как ожидалось.
Весь исходный код MyTransformer:
class MyTransformer(ast.NodeTransformer):
def visit_For(self, node):
"""
For nodes: replace with nothing
"""
print("removing a For node")
return None