2012-03-29 7 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': {}} 

ここからさらに1つの辞書'other_config': {'is_guest_installer_network': 'true', 'netmask': '255.255.255.0', 'ip_end': '192.168.128.254', 'ip_begin': '192.168.128.1'}があります。

私はnrec["other_config"]["is_guest_installer_network"]== "true"を行っているが、問題は、いくつかの属性が空の値または別の値のいずれかで、このother_config性質を持っているis_guest_installer_network=="true"

を確認したいです。この場合、私のソリューションは例外をスローします。ですから、is_guest_installer_networkが辞書で構成されていて、値(文字列)が真であるかどうかのような効率的な方法でやりたいのです。

+1

値が存在しない場合は、何を返すか: 'False'? – moooeeeep

答えて

3

これが設定項目の場合、頻繁にアクセスする必要はありません(したがって、効率要件は疑わしいでしょう)。一度設定して忘れてください(例:self.is_guest_installer_network = True)。

あなたがそれを忘れることができない場合は、エントリが辞書に存在する可能性によって異なります。アイテムが欠落している可能性が高い場合は、次のようなことをすればおそらくもっと良いでしょう。アイテムのミスが、他のコンフィギュレーションのdictはexistanceチェックのためにその値以下のルックアップのために(一度だけルックアップされている場合は、いくつかのショートカット動作を取得。

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" 

しかし、これは型チェックを処理しません。 'is_guest_installer_network'nrec['other_config']に存在する場合には、その値を返します

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

たぶん最高のこの

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()'を使うことでもっとうまくいくでしょう。これは第二引数として設定可能なデフォルト値を持っています。 –

+0

@EtiennePerot - 上記のとおりです。 – dfb

0

一つの可能​​な解決策は

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

あるように何かをするには、これを試してみてください

+0

keyが存在しない場合、 'get'は' None'を返します。とにかく、+1。私自身の答えを書いている間に(今削除されている) 'get 'について忘れてしまった。 – taskinoor

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

例外を避けるために必要なのはいいですね。