好像你可以只是評估字符串,然後從那裏摘掉類型:
>>> items = ast.literal_eval('(404.5, "Hello", 5)')
>>> [{'type': type(item).__name__, 'value': item} for item in items]
[{'type': 'float', 'value': 404.5}, {'type': 'str', 'value': 'Hello'}, {'type': 'int', 'value': 5}]
當然,如果你想做更多有趣的事情,你可以訪問AST di rectly:
>>> ast.dump(ast.parse('(404.5, "Hello", 5)'))
"Module(body=[Expr(value=Tuple(elts=[Num(n=404.5), Str(s='Hello'), Num(n=5)], ctx=Load()))])"
>>> ast.parse('(404.5, "Hello", 5)').body[0].value.elts
[<_ast.Num object at 0x107fa1250>, <_ast.Str object at 0x107fa1290>, <_ast.Num object at 0x107fa12d0>]
對於除解析一個元組(如你加入到這個問題),我們仍然可以使用Python的AST解析這個更一般的事情(只要你的語法是有效的Python) 。在這種情況下,我們將創建一個ast.NodeVisitor
,它將提取我們在訪問我們關心的Python AST的每個節點時的信息。在這種情況下,我們關心Call
,Num
,Str
和Name
節點:
import ast
class Parser(ast.NodeVisitor):
def __init__(self):
self.calls = []
self.current_command = None
def visit_Call(self, node):
name = node.func.id
self.current_command = {
'type': 'command',
'name': name,
'args': []
}
self.calls.append(self.current_command)
for arg in node.args:
self.visit(arg)
self.current_command = None
def visit_Num(self, node):
if not self.current_command:
return
args = self.current_command['args']
arg = {
'type': type(node.n).__name__,
'value': node.n
}
args.append(arg)
def visit_Str(self, node):
if not self.current_command:
return
args = self.current_command['args']
arg = {
'type': 'str',
'value': node.s
}
args.append(arg)
def visit_Name(self, node):
if not self.current_command:
return
args = self.current_command['args']
arg = {
'type': 'type',
'kind': node.id
}
args.append(arg)
S = 'commandName(3, "hello", 5.0, int)'
tree = ast.parse(S)
p = Parser()
p.visit(tree)
print p.calls
我要澄清:元組顯示爲一個字符串,是一個較大的字符串,通常是一個命令如「加(1的一部分,」你好「,3)' – TheSeamau5
我認爲唯一剩下的就是問什麼是_rules_來決定什麼是事情。例如說「int」是「類型」的規則是什麼?它是否與Python標識符一樣解析?和命令只是後面有()的標識符?在這種情況下,你仍然可以使用'AST'來解析這個(這很有趣)。 – mgilson
好問題。我剛剛更新我的示例稍微複雜一些。我用「變量」替換「類型」。你會看到現在的語法不再是Python了。重點是我稍後將添加此命令可以接受的不同類型的數據,並且其語法不應與Python的語法綁定。 – TheSeamau5