2012-03-29 218 views
2

嗨,在我的代碼中有一本字典的字典。在Python中訪問字典詞典

nrec={'bridge': 'xapi1', 'current_operations': {}, 'uuid': '9ae5ca7d-e7d6-7a81-f619-d0ea33efb534', 'tags': [], 'other_config': {'is_guest_installer_network': 'true', 'netmask': '255.255.255.0', 'ip_end': '192.168.128.254', 'ip_begin': '192.168.128.1'}, 'name_label': 'Guest installer network', 'VIFs': ['OpaqueRef:dff106aa-1a94-8384-1c86-862b47c87fcf'], 'allowed_operations': [], 'PIFs': [], 'name_description': 'Network on which guests will get assigned a private local IP address', 'MTU': '1500', 'blobs': {}} 

在這裏你可以看到這本詞典裏面多了一個詞典'other_config': {'is_guest_installer_network': 'true', 'netmask': '255.255.255.0', 'ip_end': '192.168.128.254', 'ip_begin': '192.168.128.1'}在那裏。

我要檢查is_guest_installer_network=="true"

我已經做了nrec["other_config"]["is_guest_installer_network"]== "true"但問題是一些屬性有要麼是空值或不同的值,這other_config屬性。那麼在這種情況下,我的解決方案會拋出異常所以我想以一種有效的方式來做到這一點,如果is_guest_installer_network包含在字典中,並且值(字符串)爲真或不真實。

+1

如果值不存在,你想返回什麼:'False'? – moooeeeep 2012-03-29 07:20:52

回答

3

如果這是一個配置項目,你不需要經常訪問它(因此你的效率要求是有問題的)。配置一次並忘記它(例如,設置self.is_guest_installer_network = True)。

如果你不能忘記它,它將取決於字典中出現的條目的可能性。如果該物品更可能丟失,如果您執行以下操作,可能會更好。你得到一些快捷方式的行爲,如果一個項目失誤,在其他配置字典中查找只有一次(針對所有腦幹檢查和值以下查找。

def check_guest_installer_network(nrec): 
    other_config = nrec.get("other_config", None) 
    return other_config is not None and other_config.get('is_guest_installer_network', False) 

如果它更可能的是,產品在那裏,偷懶嘗試/除方法可能更適合。由於保存檢查性能,將超過額外的性能開銷時除外實際需要來處理。

def check_guest_installer_network(nrec): 
    try: 
    return nrec["other_config"]['is_guest_installer_network'] == "true" 
    except KeyError: 
    return False 

畢竟,如果這個檢查確實對一個顯著的影響整體性能,你應該把這個變量放在一個更容易訪問的地方,比在嵌套字典中,例如將其放入全局/類成員變量一次,然後享受便宜且簡單的檢查。

你應該看看cprofile module來驗證這個查找確實是軟件的瓶頸,這是值得的優化工作。你應該看看timeit module爲你的問題選擇最高性能的解決方案。

0

只是檢查

'other_config' in nrec and 'is_guest_installer_network' in nrec['other_config'] and nrec['other_config']['is_guest_installer_network'] == 'true' 
0

要檢查鑰匙字典中的使用存在:

if 'key' in dictionary: 
    # do sth 

所以,你的代碼將是:

if 'other_config' in nrec and 'is_guest_installer_network' in nrec['other_config'] and nrec['other_config']['is_guest_installer_network'] == 'true': 
    # do sth 

此外,如果你想默認值如果密鑰不在字典中,請使用get(key, default)方法:

nrec.get('other_config', default_value_here) 
-1

你已經得到了答案

nrec["other_config"]["is_guest_installer_network"]== "true" 

可以這樣寫

if nrec.has_key("other_config") and type(nrec["other_config"]) == type({}) and nrec["other_config"].has_key("....") and nrec["other_config"]["is_guest_installer_network"]== "true": 

但是,這是有點難看。

或者,如在評論

nrec.get("other_config",{}).get("is_guest_installer_network",{}) == "true" 

指出但這不處理的類型檢查。

也許最好做這樣的事情

def traverse(_dict, keys): 
    val = _dict 
    for key in keys[:-1]: 
     if key in val and type(val[key]) is dict : 
      val = val[key] 
     else: 
      return None 
    return val.get(keys[-1],None) 
+0

-1:通過在詞典中使用本地方法'.get()',可以做得更好,它的默認值可以配置爲第二個參數。 – 2012-03-29 07:21:45

+0

@EtiennePerot - 你說的對,如上所述。 – dfb 2012-03-29 07:38:45

0

一個可能的解決方案是

>>> try: 
    if nrec["other_config1"]["is_guest_installer_network"] == 'true': 
     print 'Do Something' 
except (KeyError,TypeError): 
    None #Or do something logical 
3

試試這個:

nrec["other_config"].get('is_guest_installer_network') 

如果存在nrec['other_config']'is_guest_installer_network'它會返回它的值

+0

值得一提的是,如果key不存在,那麼'get'將返回'None'。無論如何,+1這個。在寫我自己的答案(現在已刪除)時,我忘了「get」。 – taskinoor 2012-03-29 07:54:28

0

避免異常的最佳方法是使用try .. except或使用dictionary內置方法。

my_dict = {'one': {'two': 'hello world!'}, 'four': 'Dummy!'} 
try: 
    my_name = my_dict['one']['two'] 
except: 
    pass 
    // instead of pass, you can also return something or do something else 

try: 
    my_dict['one']['two'] 
except Exception as e: 
    my_name = 'default' 
    return my_name, e // returns a tuple which contains 'default' and error message 


#or use has_key() 

# this is for one-level nested dictionary 
for id, items in my_dict.iteritems(): 
    if items.has_key('two'): 
      //do something 

# or simply this --> eliminates dummy for loop 
if my_dict['one'].has_key('two'):  // has_key returns True/False 
     // do something 

# or use in operator (replace has_key) 
if 'two' in my_dict['one'].keys(): 
    // do something 


# or get method 

my_dict['one'].get('two', 'Default') 

如果這就是你需要避免異常的好處,