2012-07-28 165 views
8

我有一个包含字典的字典,其中可能还包含字典,例如Python - 访问嵌套在字典中的值

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

目前我拆包得到“收单”的ID 001“交易编号” 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'] 

是否有向下钻取的嵌套字典,而无需解压到一间简单的方法即时变量?

+6

你觉得这条线实际上应该起作用。 – 2012-07-28 11:57:13

回答

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

实际工作。 transactions['Transaction Details']是表示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 
+0

令人难以置信的帮助 - 非常感谢! – user1530213 2012-07-28 13:05:29

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 
+0

我希望你不要介意,我添加了一个编辑来澄清这个函数的真正的动态搜索能力。能够即时传递搜索关键字列表的能力使其超越了其他技术。 – 2015-03-09 12:55:03

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 
>>> 

这里的另一种方式,变量 '名称' 指的是 'DBO [' M '] [' d '] [' V '] [' 版本'] ',这似乎更短,更整齐。

此方法不会抛出KeyError。如果没有找到钥匙,你会得到'无'。

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

+0

如果你尝试name ='m__foo__v__foo',它会抛出一个TypeError: TypeError:descriptor'get'需要'dict'对象但收到'NoneType' – krasnaya 2016-04-04 18:18:31