9

我有一本包含字典的字典,其中也可能包含字典,例如

dictionary = {'ID': 0001, 'Name': 'made up name', 'Transactions':
               {'Transaction Ref': 'a1', 'Transaction Details':
                  {'Bill To': 'abc', 'Ship To': 'def', 'Product': 'Widget A'
                      ...} ...} ... }

目前我正在拆包以获取 ID 001 的“Bill To”,“Transaction Ref”a1 如下:

if dictionary['ID'] == 001:
    transactions = dictionary['Transactions']
        if transactions['Transaction Ref'] == 'a1':
            transaction_details = transactions['Transaction Details']
            bill_to = transaction_details['Bill To']

我不禁认为这有点笨拙,尤其是最后两行-我觉得以下内容应该可行:

bill_to = transactions['Transaction Details']['Bill To']

有没有一种更简单的方法可以深入到嵌套字典中而不必解压缩到临时变量中?

4

3 回答 3

20

你可以使用这样的东西:

>>> def lookup(dic, key, *keys):
...     if keys:
...         return lookup(dic.get(key, {}), *keys)
...     return dic.get(key)
...
>>> d = {'a':{'b':{'c':5}}}
>>> print lookup(d, 'a', 'b', 'c')
5
>>> print lookup(d, 'a', 'c')
None

此外,如果您不想将搜索键定义为单独的参数,则可以将它们作为列表传递,如下所示:

>>> print lookup(d, *['a', 'b', 'c'])
5
>>> print lookup(d, *['a', 'c'])
None
于 2012-07-28T13:43:05.447 回答
15
bill_to = transactions['Transaction Details']['Bill To']

确实有效。transactions['Transaction Details']是一个表示 a 的表达式dict,因此您可以在其中进行查找。不过,对于实际程序,我更喜欢嵌套字典的 OO 方法。collections.namedtuple对于快速设置一堆只包含数据(并且没有它们自己的行为)的类特别有用。

有一个警告:在某些设置中,您可能希望KeyError在进行查找时捕获,并且在此设置中,这也有效,很难判断哪个字典查找失败:

try:
    bill_to = transactions['Transaction Details']['Bill To']
except KeyError:
    # which of the two lookups failed?
    # we don't know unless we inspect the exception;
    # but it's easier to do the lookup and error handling in two steps
于 2012-07-28T12:03:51.027 回答
2

以下是访问嵌套字典的另一种方式

>>> dbo={'m':{'d':{'v':{'version':1}}}}
>>> name='m__d__v__version' # it'll refer to 'dbo['m']['d']['v']['version']', '__' is the separator
>>> version = reduce(dict.get, name.split('__'), dbo)
>>> print version
1
>>>

在这里,变量 'name' 指的是 'dbo['m']['d']['v']['version']',看起来更短更简洁。

此方法不会抛出 KeyError。如果未找到密钥,则您将得到“无”。

参考:http ://code.activestate.com/recipes/475156-using-reduce-to-access-deeply-nested-dictionaries/

于 2014-12-16T11:51:53.003 回答