Я не знаком с модулем AST и был бы признателен за любую информацию. Если, например, у меня есть строка, содержащая допустимый скрипт Python, такой как
import sys #Just any module
class SomeClass:
def __init__(self):
self.x = 10
self.b = 15
def a_func(self):
print(self.x)
Я хотел бы иметь возможность программно редактировать строки, такие как изменение self.x = 10
на что-то вроде self.x = 20
. Я могу немного разбить его на ast
через:
some_string = "..." #String of class above
for body_item in ast.parse(some_string):
...
Но это не похоже на «правильный» путь (не то, чтобы это был правильный путь, поскольку это несколько ниша). Я надеялся, что кто-то может исправить меня на что-то более чистое или просто лучше.
Вы можете начать с использования ast.dump
, чтобы получить представление о структуре AST кода, с которым вы имеете дело:
import ast
code='self.x = 10'
print(ast.dump(ast.parse(code), indent=2))
Это выводит:
Module(
body=[
Assign(
targets=[
Attribute(
value=Name(id='self', ctx=Load()),
attr='x',
ctx=Store())],
value=Constant(value=10))],
type_ignores=[])
Из которого вы можете видеть, что вы хотите искать, это узел Assign
, где первый из targets
является узлом Attribute
, а value
является узлом Name
с id
из 'self'
и attr
из 'x'
.
Обладая этими знаниями, вы можете затем использовать ast.walk
для обхода узлов AST, чтобы найти узел с вышеупомянутыми свойствами, изменить его value
на узел Constant
с value
из 20
и, наконец, использовать ast.unparse
для преобразования AST обратно в строку кода. :
import ast
code = '''
import sys #Just any module
class SomeClass:
def __init__(self):
self.x = 10
self.b = 15
def a_func(self):
print(self.x)
'''
tree = ast.parse(code)
for node in ast.walk(tree):
if (
isinstance(node, ast.Assign) and
isinstance((target := node.targets[0]), ast.Attribute) and
isinstance(target.value, ast.Name) and
target.value.id == 'self' and
target.attr == 'x'
):
node.value = ast.Constant(value=20)
print(ast.unparse(tree))
Это выводит:
class SomeClass:
def __init__(self):
self.x = 20
self.b = 15
def a_func(self):
print(self.x)
Обратите внимание, что для ast.unparse
требуется Python 3.10 или более поздней версии. Если вы используете более раннюю версию, вместо этого вы можете использовать astunparse.unparse
из пакета astunparse.