Доступ к словарю словаря в Python - PullRequest
2 голосов
/ 29 марта 2012

Привет, в моем коде есть словарь словаря.

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 состоит из словаря, а значение (строка) истинно или нет.

Ответы [ 7 ]

3 голосов
/ 29 марта 2012

Попробуйте:

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

Он вернет свое значение, если 'is_guest_installer_network' существует в nrec['other_config']

3 голосов
/ 29 марта 2012

Если это элемент конфигурации, вам не нужно обращаться к нему очень часто (поэтому ваши требования к эффективности могут быть сомнительными). Настройте один раз и забудьте об этом (например, установите 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 , чтобы убедиться, что этот поиск действительно является узким местом вашего программного обеспечения, что стоит усилий по оптимизации. И вы должны взглянуть на модуль timeit , чтобы выбрать наиболее эффективное решение для вашей проблемы.

0 голосов
/ 29 марта 2012

Лучше всего избегать исключений: либо 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')

Получить это хорошо, если это все, что вам нужно, чтобы избежать исключения.

0 голосов
/ 29 марта 2012

Одним из возможных решений является

>>> try:
    if nrec["other_config1"]["is_guest_installer_network"] == 'true':
        print 'Do Something'
except (KeyError,TypeError):
    None #Or do something logical
0 голосов
/ 29 марта 2012

У вас есть ответ

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 голосов
/ 29 марта 2012

Чтобы проверить, существует ли ключ в словаре, используйте:

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

Дополнительно, если вы хотите использовать значение по умолчанию, если ключ не указан в файле dict, используйте get(key, default) метод:

nrec.get('other_config', default_value_here)
0 голосов
/ 29 марта 2012

Просто проверьте

'other_config' in nrec and 'is_guest_installer_network' in nrec['other_config'] and nrec['other_config']['is_guest_installer_network'] == 'true'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...