¿Cómo puedo acceder a un diccionario profundamente nested utilizando tuplas?

Me gustaría ampliar el ejemplo de autovivificación dado en una respuesta anterior de nosklo para permitir el acceso al diccionario por tupla.

La solución de nosklo es así:


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 

Pruebas:

 a = AutoVivification() a[1][2][3] = 4 a[1][3][3] = 5 a[1][2]['test'] = 6 print a 

Salida:

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

Tengo un caso en el que quiero establecer un nodo dada una tupla arbitraria de subíndices. Si no sé cuántas capas de profundidad tendrá la tupla, ¿cómo puedo diseñar una manera de establecer el nodo apropiado?

Estoy pensando que quizás podría usar una syntax como la siguiente:

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

Pero estoy teniendo problemas para encontrar una implementación que funcione.


Actualizar

Tengo un ejemplo completamente funcional basado en la respuesta de @ 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) 

Lo que puede lograr el mismo resultado que arriba utilizando la notación de sector extendida:

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

Esto parece funcionar

 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)