У меня была проблема с IE7 и возвращающим false прежде.
Проверка мой ответ здесь на другую проблему: JavaScript, не работающий на IE
ast .visit
- если, конечно, вы не переопределите его в подклассе - когда вызывается для посещения ast.Node
класса foo
, вызывает 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
Но предположим, что мы этого не сделали. t заботиться о загрузочных узлах (и их дочерних узлах - если они есть ;-). Тогда простой способ справиться с этим может быть, например:
>>> 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
или, предположим, мы также хотели увидеть фактические имена для узлов Name; then ...:
>>> 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
- - обычно вас интересуют только несколько типов узлов,
generic_visit
вызывается, когда пользовательский посетитель (например, visit_Name) не может быть найден. Вот фрагмент кода, который я недавно написал с помощью ast.NodeVisitor: https://bitbucket.org/pypy/pypy/src/6df19fd2b6df6058daf162100cf7ee4521de5259/py/_code/_assertionnew.py?at=default&fileview-defileviewer=file 111680] Он интерпретирует узлы AST, чтобы получить отладочную информацию о некоторых из них, и возвращается к generic_visit
, когда не предусмотрена специальная реализация.