2013-02-25 1 views
4

Я хотел бы остановиться на the autovivification example, приведенном в предыдущем ответе от nosklo, чтобы разрешить доступ к словарю с помощью кортежа. РешениеКак получить доступ к глубоко вложенному словарю с помощью кортежей?

nosklo выглядит следующим образом:


class AutoVivification(dict): 
    """Implementation of perl's autovivification feature.""" 
    def __getitem__(self, item): 
     try: 
      return dict.__getitem__(self, item) 
     except KeyError: 
      value = self[item] = type(self)() 
      return value 

Тестирование:

a = AutoVivification() 

a[1][2][3] = 4 
a[1][3][3] = 5 
a[1][2]['test'] = 6 

print a 

Выход:

{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}} 

У меня есть случай, когда я хочу установить узел, учитывая некоторый произвольный набор индексов. Если я не знаю, сколько слоев в глубине кортежа будет, как я могу создать способ установить соответствующий узел?

Я думаю, что, возможно, я мог бы использовать синтаксис вроде следующего:

mytuple = (1,2,3) 
a[mytuple] = 4 

Но у меня возникают проблемы, придумывающая рабочей реализации.


Update

У меня есть полностью рабочий пример на основе @ ответ JCash в:

class NestedDict(dict): 
    """                  
    Nested dictionary of arbitrary depth with autovivification.    

    Allows data access via extended slice notation.       
    """ 
    def __getitem__(self, keys): 
     # Let's assume *keys* is a list or tuple.        
     if not isinstance(keys, basestring): 
      try: 
       node = self 
       for key in keys: 
        node = dict.__getitem__(node, key) 
       return node 
      except TypeError: 
      # *keys* is not a list or tuple.        
       pass 
     try: 
      return dict.__getitem__(self, keys) 
     except KeyError: 
      raise KeyError(keys) 
    def __setitem__(self, keys, value): 
     # Let's assume *keys* is a list or tuple.        
     if not isinstance(keys, basestring): 
      try: 
       node = self 
       for key in keys[:-1]: 
        try: 
         node = dict.__getitem__(node, key) 
        except KeyError: 
         node[key] = type(self)() 
         node = node[key] 
       return dict.__setitem__(node, keys[-1], value) 
      except TypeError: 
       # *keys* is not a list or tuple.        
       pass 
     dict.__setitem__(self, keys, value) 

который может достичь такой же вывод, как указано выше с использованием расширенной нотации среза:

d = NestedDict() 
d[1,2,3] = 4 
d[1,3,3] = 5 
d[1,2,'test'] = 6 

ответ

4

Это, похоже, работает

def __setitem__(self, key, value): 
    if isinstance(key, tuple): 
     node = self 
     for i in key[:-1]: 
      try: 
       node = dict.__getitem__(node, i) 
      except KeyError: 
       node = node[i] = type(self)() 
     return dict.__setitem__(node, i, value) 
    return dict.__setitem__(self, key, value) 
+0

Ошибка 'node = node [i] = type (self)()' работает некорректно. Мне пришлось разбить это на две отдельные задания. Ты знаешь почему? –

+0

Хмм, нет, я не знаю, я боюсь. – JCash

 Смежные вопросы

  • Нет связанных вопросов^_^