Использование модуля ast для преобразования случайных констант в исходный код Python

Я заинтересован в написании программы, которая использует встроенный в Python модуль AST для случайного изменения констант в произвольном исходном коде Python.

Это преобразование, вероятно, будет связано с обходом представления абстрактного синтаксического дерева с использованием операций, определенных модулем AST. Модуль предлагает две опции: во-первых, ast.walk () возвращает ссылки на все узлы в AST, но не предоставляет никакой контекстной информации, делая невозможной повторную сборку дерева. Во-вторых, документация описывает второй метод, включающий класс ast.NodeTransformer: несколько источников документации описывают, как использовать NodeTransformer.

Однако в документации NodeTransformer не упоминается, как случайным образом применять условные замены к AST. В частности, я хотел бы изменить эту функцию, чтобы создать функцию, которая выбирает случайный узел в ast, выбирает постоянную, связанную с узлом в случайном порядке, и заменяет эту константу случайно выбранной константой того же типа.

Я подозреваю, что изо всех сил пытаюсь понять, как правильно изменить NodeTransformer, потому что я редко программирую в объектно-ориентированном стиле (обычно придерживаясь функциональной парадигмы). Надеюсь, что направить меня в правильном направлении легко придет к одному из вас.

1 ответ

Решение

Если все, что вы хотите сделать, это изменить константы случайным образом, то вам не нужен контекст узла. Вы можете просто пройтись по дереву, ища постоянные узлы, и, если вы видите один, изменить его значение. Вот простой пример:

source = """
x = 2
"""

# exec the source as-is
mod = {}
exec compile(source, '<blah>', 'exec') in mod

print(mod['x'])
# prints 2

t = ast.parse(source)
# change all numerical constants to 8
for node in ast.walk(t):
    if isinstance(node, ast.Num):
        node.n = 8
# exec the modified AST
modMod = {}
exec compile(t, '<blah>', 'exec') in modMod

print(modMod['x'])
# prints 8

Если вы хотите сделать случайный выбор относительно изменения константы, вы также можете сделать это. Я не уверен, что понимаю ваше утверждение о выборе "случайного узла в AST". Иерархическая природа AST означает, что случайным узлом может быть что угодно, от одной константы до всего модуля, поэтому кажется немного странным сначала выбрать случайный узел, а затем выбрать постоянный узел внутри него. Почему бы просто не выбрать случайный постоянный узел в первую очередь?

Другие вопросы по тегам