如何编写 ast.NodeTransformer 将 a=1 转换为函数调用 a=variables("a")?

How can I write an ast.NodeTransformer to convert a=1 to a function call a=variables("a")?

python 文档和 greentreesnakes 表明可以使用 ast.NodeTransformer 通过 AST 更改 python 代码:

我想将 a=1 之类的作业更改为 a=variables(1)

我对 ctx 是什么以及何时需要它感到有点困惑,astor 的输出似乎没有它,但似乎需要它。

您不一定需要 NodeTransformer 来执行此操作。如果您已经拥有 AST 并且知道该节点(在本例中为 Assign 节点),您可以按如下方式就地修改。

import ast

src = 'a = 1'
code = 'variables(1)'

tree = ast.parse(src)
assign_node = tree.body[0]
assign_node.value = ast.parse(code).body[0].value

更新后的 AST 可以进一步用于您的任何目的。例如,您可以生成源代码(在上例中使用 astor 模块作为 astor.to_source(tree))。 NodeTransformer 如果您需要在给定条件的情况下查找节点,则非常方便。它具有类似于 NodeVisitorvisit_* 功能,可让您就地执行此操作。如下所示:

from ast import parse, NodeTransformer

class ChangeAssignment(NodeTransformer):
    
    def visit_Assign(self, node):
        if assign_node.targets[0].id == 'a':
            node.value = parse('variables(1)').body[0].value
            
        return node

src = 'a = 1'            

t = ChangeAssignment()
tree = parse(src)
tree = t.visit(tree)

变量的ctx决定了它是用于加载、存储还是删除变量。如果你直接创建节点(上面我使用 parse 隐式创建节点),则需要它。对于修改 AST 或生成源代码(如 astor.to_source),使用什么 ctx 并不重要。但是,如果你直接将 AST 传递给 Python compile 函数,如果没有使用正确的 ctx 它会报错。