pyparsing中asDict()与asList()解析结果不一致问题咨询
PyParsing中asDict()与asList()返回结果不一致的问题解析
问题重现
使用pyparsing编写解析逻辑时,发现asDict()返回的value被包裹为列表,而asList()返回扁平化的单个值,不符合预期。
代码示例:
import pyparsing as pp WALRUS = pp.Keyword(':=').suppress() number = pp.pyparsing_common.number hex_number = pp.Literal('16#').suppress() + pp.Word(pp.hexnums+'_') YesNo = pp.CaselessKeyword('YES').setParseAction(lambda t: True)\ | pp.CaselessKeyword('NO').setParseAction(lambda t: False) dblQuoString = pp.dblQuotedString().addParseAction(pp.removeQuotes) propertyName = pp.Word(pp.alphas)('key') value = pp.MatchFirst([dblQuoString, YesNo, hex_number, number, pp.Word(pp.alphanums + '.')] ) value.setDebug() key_value = propertyName + WALRUS + value('value') if __name__ == "__main__": test_string = r"""Description := "Anything" """ r = key_value.parseString(test_string) print(r.asDict()) print(r.asList())
运行输出:
{'key': 'Description', 'value': ['Anything']} ['Description', 'Anything']
原因分析
问题出在hex_number的定义上:
hex_number = pp.Literal('16#').suppress() + pp.Word(pp.hexnums+'_')
这是两个表达式的组合(Literal + Word),即使Literal被suppress(),整个表达式返回的ParseResults仍然是列表结构(仅包含Word的结果)。
MatchFirst会保留所有分支的返回结构类型,只要有一个分支返回列表,整个value的解析结果就会以列表形式存储。asDict()会严格保留这个嵌套结构,而asList()会自动扁平化嵌套列表,因此出现结果不一致的现象。
解决方案
要让value始终返回单个值,有两种常见处理方式:
方式1:修改hex_number的返回结构
给hex_number添加解析动作,将列表转换为单个元素:
hex_number = (pp.Literal('16#').suppress() + pp.Word(pp.hexnums+'_')).setParseAction(lambda t: t[0])
方式2:统一处理value的返回结果
给value添加解析动作,确保最终返回单个值:
value = pp.MatchFirst([dblQuoString, YesNo, hex_number, number, pp.Word(pp.alphanums + '.')] ).setParseAction(lambda t: t[0])
修改后运行代码,输出会符合预期:
{'key': 'Description', 'value': 'Anything'} ['Description', 'Anything']
内容的提问来源于stack exchange,提问作者DamirX
相关产品推荐
相关产品推荐

