处理存储在字典中的解析变量

Handling parsed variables stored in dictionary

是否有更好、更 pythonic 的方法来解析和设置变量值(存储在 var_dict 字典中)并从中获取值?

下面的代码完全可以工作,但尤其是设置和获取部分看起来太复杂了。

from pyparsing import Word, nums, Forward, ZeroOrMore, alphas, alphanums, Group, Combine

def test_grammar():
    number  = Word(nums)
    itemlist = Forward()
    items = (number | itemlist)
    itemlist << ('[' + items + ZeroOrMore(',' + items) + ']')
    variable = Word(alphas, alphanums+"_")("variable")
    data = itemlist("data")
    assignment = Group(variable + '=' + data)("assignment")
    indexes  = ZeroOrMore('[' + number + ']')("index")
    query    = Combine(variable + indexes)("query")
    action   = assignment | query
    return action

var_dict = {}

test_input1 = "nl = [1, [2, 3]]"
test_input2 = "nl[1][1]"

tokens1 = test_grammar().parseString(test_input1)
variable = tokens1['assignment']['variable']
data = ''.join(tokens1['assignment']['data'])
var_dict[variable] = eval(data)
print var_dict['nl']

tokens2 = test_grammar().parseString(test_input2)
variable = tokens2['query']['variable']
index = ''.join(tokens2['query']['index'])
print eval("var_dict['" + variable + "']" + index)

按需制作:

[1, [2, 3]]
3

eval() 通常表示采取了有时是危险的捷径,而不是使用语言本身来表达解决方案。要么是出于懒惰,要么是缺乏语言知识。两个 eval() 调用都可以避免。

第一个用于解析可以通过 pyparsings 解析操作处理的数字列表。

第二个只是为了避免简单的循环。

from pyparsing import (
    Word, nums, Forward, ZeroOrMore, alphas, alphanums, Group, Combine, Suppress
)


def test_grammar():
    number = Word(nums).setParseAction(lambda toks: int(toks[0]))
    itemlist = Forward()
    items = number | itemlist
    itemlist << Group(
        Suppress('[')
        + items
        + ZeroOrMore(Suppress(',') + items)
        + Suppress(']')
    ).setParseAction(lambda toks: list(toks))
    variable = Word(alphas, alphanums + '_')('variable')
    data = itemlist('data')
    assignment = Group(variable + '=' + data)('assignment')
    indexes = ZeroOrMore(Suppress('[') + number + Suppress(']'))('indexes')
    query = Combine(variable + indexes)('query')
    action = assignment | query
    return action


def main():
    variables = dict()

    test_input_a = 'nl = [1, [2, 3]]'
    test_input_b = 'nl[1][1]'

    grammar = test_grammar()
    tokens = grammar.parseString(test_input_a)
    data = tokens['assignment']['data'][0]
    variables[tokens['assignment']['variable']] = data
    print variables['nl']

    tokens = grammar.parseString(test_input_b)
    data = variables[tokens['query']['variable']]
    for index in tokens['query']['indexes']:
        data = data[index]
    print data


if __name__ == '__main__':
    main()