0

我有兴趣编写一个程序,该程序使用 Python 的内置AST 模块来随机修改任意 Python 源中的常量。

这种转换可能涉及使用 AST 模块定义的操作遍历抽象语法树表示。该模块提供了两个选项:首先,ast.walk()返回对 AST 中所有节点的引用,但不提供任何上下文信息,因此无法重新组装树。其次,文档描述了涉及ast.NodeTransformer类的第二种方法:几个文档来源一般描述了如何使用 NodeTransformer。

但是,NodeTransformer 文档没有提到如何将条件替换随机应用于 AST。具体来说,我想修改此功能以创建一个函数,该函数在 ast 中选择一个随机节点,随机选择与该节点关联的常数,并将该常数替换为随机选择的相同类型的常数。

我怀疑我很难理解如何正确修改 NodeTransformer,因为我很少以面向对象的风格进行编程(通常遵循功能范式)。希望将我指向正确的方向会很容易对你们中的一个人来说。

4

1 回答 1

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 的分层特性意味着随机节点可以是从单个常量到整个模块的任何内容,因此首先选择一个随机节点然后在其中选择一个常量节点似乎有点奇怪。为什么不首先选择一个随机常数节点?

于 2016-12-27T04:34:22.833 回答