2012-07-28 56 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