我正在使用Python ast
模块来解析像X >= 13 and Y == W
这样的表达式。我需要的是在下面的预订字典中转换这个表达式:
{
"function": "and",
"args": [
{
"function": ">=",
"args": [
{
"variable": "X"
},
{
"value": 13
}
]
},
{
"function": "==",
"args": [
{
"variable": "Y"
},
{
"variable": "W"
}
]
}
]
}
Python AST为我提供了从值验证语法和差异变量的好处。以下代码进行了基本的解析,但注意输出不是预订的,我不完全确定如何处理:
import ast
class ExclusionParser(ast.NodeVisitor):
tree = ''
def append(self, expr):
self.tree += expr
def visit_And(self, node):
self.append("and ")
def visit_Lt(self, node):
self.append("< ")
def visit_Gt(self, node):
self.append("> ")
def visit_Eq(self, node):
self.append("== ")
def visit_Num(self, node):
self.append("value: %s " % node.n)
def visit_Name(self, node):
self.append("variable: %s " % node.id)
def generic_visit(self, node):
"""Called if no explicit visitor function exists for a node."""
self.append("(")
for field, value in ast.iter_fields(node):
if isinstance(value, list):
for item in value:
if isinstance(item, ast.AST):
self.visit(item)
elif isinstance(value, ast.AST):
self.visit(value)
self.append(")")
if __name__ == '__main__':
v = ExclusionParser()
p = ast.parse("X > 13 and Y == W")
v.visit(p)
print(v.tree)
输出
(((and (variable: X > value: 13 )(variable: Y == variable: W ))))
答案 0 :(得分:1)
考虑这些小改动 - 我已经添加了'
和逗号:
import ast
class ExclusionParser(ast.NodeVisitor):
tree = ''
def append(self, expr):
self.tree += expr
def visit_And(self, node):
self.append("'func:and', ")
def visit_Lt(self, node):
self.append("'func:lt', ")
def visit_Gt(self, node):
self.append("'func:gt', ")
def visit_Eq(self, node):
self.append("'func:eq', ")
def visit_Num(self, node):
self.append("'value:%s', " % node.n)
def visit_Name(self, node):
self.append("'variable:%s', " % node.id)
def generic_visit(self, node):
"""Called if no explicit visitor function exists for a node."""
self.append("[")
for field, value in ast.iter_fields(node):
if isinstance(value, list):
for item in value:
if isinstance(item, ast.AST):
self.visit(item)
elif isinstance(value, ast.AST):
self.visit(value)
self.append("], ")
if __name__ == '__main__':
v = ExclusionParser()
p = ast.parse("X > 13 and Y == W")
v.visit(p)
tree = ast.literal_eval(v.tree[:-2])
print(tree)
此时tree
是有效列表:
[[['func:and', ['variable:X', 'func:gt', 'value:13'], ['variable:Y', 'func:eq', 'variable:W']]]]
如果您已经写过generic_visit
,那么在编写另一个将列表列表转换为字典的递归函数时,您不应该遇到任何困难。解决方案有点hacky。 (并且通过&#34;一点&#34;我的意思是它非常hacky。)我认为正确的解决方案是修改generic_visit
。
另外注意:字典不会保留其元素的顺序。使用OrderedDict
确保function
密钥首先出现。