python - ast.fix_missing_locations 何时更改树?

标签 python abstract-syntax-tree

我试图找到一个示例,其中 NodeTransformer 继承者的访问NodeTransformer访问不同 继承者在树上使用fix_missing_locations

这是来自 documentation 的示例(由于某种原因,这不起作用,即树不会改变,具体取决于我们是否应用 fix_missing_locations ):

from ast import *


class RewriteName(NodeTransformer):

    def visit_Name(self, node):
        return Subscript(
            value=Name(id='data', ctx=Load()),
            slice=Constant(value=node.id),
            ctx=node.ctx
        )


tree = parse('foo', mode='eval')
new_tree = fix_missing_locations(RewriteName().visit(tree))
new_uncorrected_tree = RewriteName().visit(tree)

new_tree_str = dump(new_tree, include_attributes=True)
new_uncorrected_tree_str = dump(new_uncorrected_tree, include_attributes=True)

print(new_tree_str == new_uncorrected_tree_str)  # True

最佳答案

上述代码的问题如下:

...

tree = parse('foo', mode='eval')
new_uncorrected_tree = RewriteName().visit(tree)
new_uncorrected_tree2 = RewriteName().visit(tree)
new_tree = fix_missing_locations(new_uncorrected_tree2)

print(
    tree is new_uncorrected_tree,   # True
    tree is new_uncorrected_tree2,  # True
    tree is new_tree)               # True

treenew_un Corrected_tree1new_un Corrected_tree2new_tree 是同一个对象,因此,它们是相等的并且使用它们的所有操作(例如创建字符串表示形式)都将产生相同的结果。

如果我们最初使用不同的对象,那么结果将是两个完全不同的字符串:

...

tree1 = parse('foo', mode='eval')
tree2 = parse('foo', mode='eval')
new_tree = fix_missing_locations(RewriteName().visit(tree1))
new_uncorrected_tree = RewriteName().visit(tree2)

print(tree1 is tree2)  # False

new_tree_str = dump(new_tree, include_attributes=True)
new_uncorrected_tree_str = dump(new_uncorrected_tree, include_attributes=True)

print(dump(new_tree) == dump(new_uncorrected_tree))  # True
print(new_tree_str == new_uncorrected_tree_str)      # False

print(tree1 is tree2) - 由于 tree1tree2 是不同的对象,因此 new_treenew_un Corrected_tree 也是不同的对象。

print(dump(new_tree) == dump(new_un Corrected_tree)) - 尽管这些对象的字符串表示形式(很可能是值)是相同的。

print(new_tree_str == new_un Corrected_tree_str) - 在这里我们可以看到 RewriteName 没有填写 new_un Corrected_tree 中的属性,而 fix_missing_locations 做到了,这就是我们看到差异的原因。

如果我们打印出树木,我们可以更清楚地看到差异:

print(dump(new_tree, include_attributes=True, indent=4))
print(dump(new_uncorrected_tree, include_attributes=True, indent=4))
Expression(
    body=Subscript(
        value=Name(
            id='data',
            ctx=Load(),
            lineno=1,
            col_offset=0,
            end_lineno=1,
            end_col_offset=0),
        slice=Constant(
            value='foo',
            lineno=1,
            col_offset=0,
            end_lineno=1,
            end_col_offset=0),
        ctx=Load(),
        lineno=1,
        col_offset=0,
        end_lineno=1,
        end_col_offset=0))
Expression(
    body=Subscript(
        value=Name(id='data', ctx=Load()),
        slice=Constant(value='foo'),
        ctx=Load()))

但是我们也可以简单地通过从相同的值创建相同类型的对象来获得这样的结果:

class RewriteName(NodeTransformer):
    def visit_Name(self, node):
        return Name(node.id, node.ctx)

这是因为在创建节点对象时,我们没有指定它的所有属性,这正是 parse 函数中发生的情况。

关于python - ast.fix_missing_locations 何时更改树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68854310/

相关文章:

c# - Microsoft CCI - 编写编译器的资源和引用

python - 如何在 Flask 中设置 Inherited MethodView 对 sqlalchemy 模型进行 CRUD 操作

Python:二进制到 Base64

python - 如何在 tf.estimator.Estimator() 中记录 tensorflow 层输出

c++ - 取消引用的列表迭代器段错误

java - HQL 意外的 AST 节点 : min

java - hibernate 6 : What is SQM?

Python:幸运七人制游戏(平均掷骰子次数)

python - 如何在 Python 中的每一行的第 n 个位置创建一个字符串列表

javascript - 什么是 JSXIdentifier 以及它与 AST 中的 Identifier 有何不同?