Creación de diccionario usando elementos de lista / tupla como clave

Necesito generar un diccionario como este:

{ 'newEnv': { 'newProj': { 'newComp': { 'instances': [], 'n_thing': 'newThing' } } } } 

de una tupla, como esto: ('newEnv','newProj','newComp','newThing') pero solo si eso no existe ya. Entonces, he intentado esto:

 myDict = {} (env,proj,comp,thing) = ('newEnv','newProj','newComp','newThing') if env not in myDict: myDict[env] = {} if proj not in myDict[env]: myDict[env][proj] = {} if comp not in myDict[env][proj]: myDict[env][proj][comp] = {'n_thing': thing, 'instances': []} 

que está funcionando bastante bien pero no estoy seguro de cuán eficiente es eso o si debería hacerlo de esta manera. Alguna sugerencia)??

Puede usar un bucle (con solo las 3 primeras claves, newThing no es una clave en la cadena):

 myDict = {} path = ('newEnv','newProj','newComp') current = myDict for key in path: current = current.setdefault(key, {}) 

donde la current termina como el diccionario más interno, permitiéndole establecer las 'n_thing' y 'instances' en eso.

Podrías usar reduce() para contraer eso en una sola línea:

 myDict = {} path = ('newEnv','newProj','newComp') reduce(lambda d, k: d.setdefault(k, {}), path, myDict) 

La llamada reducida devuelve el diccionario más interno, por lo que puede usarlo para asignar su valor final:

 myDict = {} path = ('newEnv','newProj','newComp') inner = reduce(lambda d, k: d.setdefault(k, {}), path, myDict) inner.update({'n_thing': 'newThing', 'instances': []}) 

puede hacer algo similar, tal vez un poco más simple, con un código predeterminado de elementos predeterminados (consulte el código predeterminado de código predeterminado, nested para alguna discusión)

 tree = lambda: defaultdict(tree) base = tree() for x in mytuple[:-2]: base = base[x] base[x] = mytuple[-1] 

que es muy similar a la de martijn, simplemente utilizando la funcionalidad predeterminada para crear los subdictos en lugar de hacerlo directamente con setdefault .

esto también te permite escribir directamente

 myDict[env][proj][comp].setdefault('instances', list()).append(queue) 

Si eso es lo que realmente estás buscando. (Lamentablemente, no hay forma de eliminar setdefault; después de todo, no sé de antemano si desea una lista o un dictado. Solo tiene un valor predeterminado) …