2009-05-11 26 views
7

Supongamos que tengo dos dicts en Python:¿Hay alguna manera de establecer múltiples valores predeterminados en un dict de Python usando otro dict?

mydict = { 'a': 0 } 

defaults = { 
    'a': 5, 
    'b': 10, 
    'c': 15 
} 

Quiero ser capaz de ampliar mydict utilizando los valores por defecto de defaults, de manera que 'a' sigue siendo el mismo, pero 'b' y 'c' están completos. Conozco dict.setdefault() y dict.update(), pero cada uno de ellos solo hace la mitad de lo que deseo - con dict.setdefault(), tengo que repetir cada variable en defaults; pero con dict.update(), defaults volará cualquier valor preexistente en mydict.

¿Hay alguna funcionalidad que no encuentre dentro de Python que pueda hacer esto? Y si no, ¿hay una manera más Pythonic de escribir un bucle para llamar repetidamente dict.setdefaults() que esto:

for key in defaults.keys(): 
    mydict.setdefault(key, defaults[key]) 

Contexto: Estoy escribiendo algunos datos en Python que controla cómo analizar un árbol XML. Hay un dict para cada nodo (es decir, cómo procesar cada nodo), y prefiero que los datos que escribo sean escasos, pero completados con los valores predeterminados. El código de ejemplo es solo un ejemplo ... el código real tiene muchos más pares clave/valor en el dict predeterminado.

(I dan cuenta de toda esta cuestión es más que un detalle sin importancia, pero me ha estado molestando, así que me preguntaba si había una mejor manera de hacer esto que no soy consciente de.)

Respuesta

7

¿No podrías hacer que mydict sea una copia del valor predeterminado, de esa manera, mydict tendría todos los valores correctos para empezar?

mydict = default.copy() 
+0

Sí, esto es lo que suelo hacer también ... – Macke

+0

Pensé en esto, pero no copiar los valores predeterminados completos sería bastante ineficiente (¿especialmente mydict tiene todos los valores establecidos para comenzar)? Estarías creando un dict nuevo, copiando todos los valores de otro, y luego reescribiendo todo el dict nuevamente en ese caso. –

+2

@Daniel Lew: los valores no se copiarán, solo las referencias a ellos. El nuevo dict tendrá nuevas referencias a los mismos valores en la memoria. – nosklo

0
defaults.update(mydict) 
+0

Entonces, ¿cómo podré aplicar mis valores predeterminados a otro nodo? –

+0

guarde una copia del original en alguna parte. – SilentGhost

+0

Primero debe hacer una copia profunda de los valores predeterminados, luego ... – Stephan202

3

Si no te importa la creación de un nuevo diccionario en el proceso, esto va a hacer el truco:

newdict = dict(defaults) 
newdict.update(mydict) 

Ahora newdict contiene lo que necesita.

5

Esto se puede hacer de la misma manera collections.DefaultDict de Python funciona:

class MultiDefaultDict(dict): 
    def __init__(self, defaults, **kwargs): 
     self.defaults = defaults 
     self.update(kwargs) 
    def __missing__(self, key): 
     return self.defaults[key] 

>>> mydict2 = MultiDefaultDict(defaults, a=0) 
>>> mydict2['a'] 
0 
>>> mydict2['b'] 
10 
>>> mydict2 
{'a': 0} 

Las otras soluciones publicadas hasta ahora se duplican todos los valores por defecto; este los comparte, según lo solicitado. Puede o no querer anular otros métodos dict como __contains __(), __iter __(), items(), keys(), values ​​() - esta clase como se define aquí itera solo sobre los elementos no predeterminados.

+0

+1 También vale la pena enfatizar que a diferencia de 'defaultdict' (y' setdefault() ') las claves que faltan y los valores predeterminados asociados * no * realmente se agregan al diccionario subyacente, lo que puede o no ser deseable. En cualquier caso, eso, por supuesto, podría cambiarse ... – martineau

0

Personalmente, me gusta agregar el objeto del diccionario. Funciona principalmente como un diccionario, excepto que primero tiene que crear el objeto.

class d_dict(dict): 
    'Dictionary object with easy defaults.' 
    def __init__(self,defaults={}): 
     self.setdefault(defaults)   
    def setdefault(self,defaults): 
     for key, value in defaults.iteritems(): 
      if not key in self: 
       dict.__setitem__(self,key,value) 

Esto proporciona la misma funcionalidad que el tipo dict excepto que reemplaza el método setdefault() y tomará un diccionario que contiene uno o más elementos. Puede establecer los valores predeterminados en la creación.

Esto es solo una preferencia personal. Como yo entiendo, todo lo que hace dict.setdefault() es establecer los elementos que aún no se han establecido. Así que, probablemente, el más simple en la opción lugar es:

new_dict = default_dict.copy() 
new_dict.update({'a':0}) 

Sin embargo, si usted hace esto más de una vez es posible hacer una función de esto.En este punto, puede ser más fácil usar un objeto dict personalizado, en lugar de agregar constantemente valores predeterminados a sus diccionarios.

Cuestiones relacionadas