字典列表与pyparsing

3 投票
1 回答
2039 浏览
提问于 2025-04-16 23:30

我正在使用pyparsing来构建字典,然后把这些字典添加到一个列表中。但是当我这样做时,字典被多包了一层列表,而且还多了一个空字典。我完全不知道该怎么解决这个问题。我想要的结果是[{},{},{}],但我得到的是[([{}],{})]。为什么getDict的代码能给我想要的结果,而getDictParse却不能呢?

#! /usr/bin/env python
from pyparsing import Literal, NotAny, Word, printables, Optional, Each, Combine, delimitedList, printables, alphanums, nums, White, OneOrMore, Group

noParseList = []
parseList   = []

def getDict():
    return {'duck':'moose','cow':'ewe'}

def getDictParse(str, loc, toks):
    return {'duck2':toks[0],'cow2':'ewe'}

parser = Word(alphanums)
parser.setParseAction(getDictParse)
parseList.append(parser.parseString("monkey"))

noParseList.append(getDict())

print noParseList
print parseList

输出:

[{'cow': 'ewe', 'duck': 'moose'}]
[([{'cow2': 'ewe', 'duck2': 'monkey'}], {})]

1 个回答

7

在Python中,虽然某个东西看起来像是一个包含列表和字典的列表,但这并不意味着它真的是那样。Python对象有一个叫做 __repr__ 的方法,它会显示一些信息,但有时候这个信息可能会让人误解。在pyparsing这个库中,parseString方法返回的是一种叫做ParseResults的对象。ParseResults的行为既像列表又像字典,所以当你打印它时,会显示出这样的元组:

(list of matched tokens, dict of named tokens)

如果你使用列表索引(也就是用数字或者切片的方式),那么ParseResults的 __getitem__ 方法会根据匹配的标记来索引列表。如果你使用键索引(也就是用非数字的键),ParseResults的 __getitem__ 方法会在命名标记的字典中用这个键来返回与这个名字相关的值,不管它的位置在哪里。如果这个键是一个有效的Python标识符,你甚至可以用对象属性的方式来访问——在这种情况下,ParseResults的 __getattr__ 方法也会用这个键在命名标记的字典中索引,但有一个不同之处:如果出现KeyError(找不到这个键),使用对象属性语法会返回一个空字符串''。下面是一个更详细的例子,跟着注释来了解不同的选项:

from pyparsing import *

# define an integer token, and a parse-time conversion function
def cvtInteger(tokens):
    return int(tokens[0])
integer = Word(nums).setParseAction(cvtInteger)

# define an animal type, with optional plural 's'
animal = Combine(oneOf("dog cat monkey duck llama") + Optional("s"))

# define an expression for some number of animals
# assign results names 'qty' and 'animal' for named access
# to parsed data tokens
inventoryItem = integer("qty") + animal("animal")

# some test cases
items = """\
    7 llamas
    1 duck
    3 dogs
    14 monkeys""".splitlines()

for item in items:
    info = inventoryItem.parseString(item)
    # print the parsed item
    print type(info), repr(info)

    # use string key to access dict item
    print info['qty']

    # use object attribute to access dict item
    print info.animal

    # use list indexing to access items in list
    print info[-1]

    # use object attribute to access
    print info.average_weight

打印结果:

<class 'pyparsing.ParseResults'> ([7, 'llamas'], {'animal': [('llamas', 1)], 'qty': [(7, 0)]})
7
llamas
llamas

<class 'pyparsing.ParseResults'> ([1, 'duck'], {'animal': [('duck', 1)], 'qty': [(1, 0)]})
1
duck
duck

<class 'pyparsing.ParseResults'> ([3, 'dogs'], {'animal': [('dogs', 1)], 'qty': [(3, 0)]})
3
dogs
dogs

<class 'pyparsing.ParseResults'> ([14, 'monkeys'], {'animal': [('monkeys', 1)], 'qty': [(14, 0)]})
14
monkeys
monkeys

所以,针对你最初的问题,你应该能够使用列表访问的方式来获取你解析操作返回的字典:

parseList.append(parser.parseString("monkey")[0])

撰写回答