Python AST:TypeError 重写节点

Python AST : TypeError Rewriting Node

我正在尝试使用 PLY 和 Python 的 AST 从头开始​​创建方程求解器。

从输入2 + x开始我先翻译成N.Number(2) + x。为什么?因为我使用自己的 Class 作为实数。

现在,我正在根据第一步的输出创建一个 AST。在这里,我想重写 'x',通过函数调用节点更改其名称节点以获得如下内容:N.Number(2) + N.Number(42).

但是我得到了这个类型错误:

Traceback (most recent call last):
  File "test_ast.py", line 52, in <module>
    print(eval(compile(yop, filename="", mode="eval")))
TypeError: required field "value" missing from Attribute

到目前为止,这是我的代码:

class RewriteName(ast.NodeTransformer):
    def visit_Name(self, node):
        if node.id == 'x':
            return ast.copy_location(ast.Call(func=ast.Attribute(value=ast.Name(id='N', ctx=ast.Load()), attr='Number', ctx=ast.Load()),
                args=[ast.Num(n=42)],
                keywords=[]
            ), node)

question = "N.Number(2) + x"
yop = ast.parse(question, mode="eval")

print(ast.dump(yop))
RewriteName().visit(yop)
print(ast.dump(yop))

print(eval(compile(yop, filename="", mode="eval")))

问题显然来自 Rewrite_Name class。注意它周围的两个印刷品:这些是它们的输出:

Expression(body=BinOp(left=Call(func=Attribute(value=Name(id='N', ctx=Load()), attr='Number', ctx=Load()), args=[Num(n=2)], keywords=[]), op=Add(), right=Name(id='x', ctx=Load())))

Expression(body=BinOp(left=Call(func=Attribute(attr='Number', ctx=Load()), args=[Num(n=2)], keywords=[]), op=Add(), right=Call(func=Attribute(value=Name(id='N', ctx=Load()), attr='Number', ctx=Load()), args=[Num(n=42)], keywords=[])))

我对 Rewrite_Name class 的调用错误地更改了表达式 BinOp 左侧的某些内容,但我不知道为什么。

有人可以帮助我吗?

我认为您收到此错误是因为当您访问第一个 Name 时,它​​的 ID 不是 x。在此代码中,您的函数 visit_Name returns None.

添加一个else: return node

class RewriteName(ast.NodeTransformer):
    def visit_Name(self, node):
        if node.id == 'x':
            return ast.copy_location(ast.Call(func=ast.Attribute(value=ast.Name(id='N', ctx=ast.Load()), attr='Number', ctx=ast.Load()),
                args=[ast.Num(n=42)],
                keywords=[]
            ), node)
        else:
            return node

将帮助您避免 required field "value" missing from Attribute...

只是为了得到另一个 TypeError: required field "lineno" missing from expr ;-)