2012-05-29 11 views
20

¿Hay alguna manera de obtener un default para devolver la clave por defecto? O alguna estructura de datos con un comportamiento equivalente? Es decir, después de inicializar el diccionario d,Diccionario de Python que por defecto es clave?

>>> d['a'] = 1 
>>> d['a'] 
1 
>>> d['b'] 
'b' 
>>> d['c'] 
'c' 

sólo he visto los diccionarios predeterminados llevan funciones que no tienen parámetros, así que no estoy seguro si hay una solución que no sea la creación de un nuevo tipo de diccionario.

+0

Esta es una tarea demasiado especializada. Sugiero que considere la posibilidad de subclasificar el objeto/tipo 'dict'. – heltonbiker

+0

Estoy intrigado por esto. ¿Puedes darme una idea de para qué lo necesitas? –

Respuesta

25

me gustaría reemplazar el método de __missing__dict:

>>> class MyDefaultDict(dict): 
...  def __missing__(self, key): 
...   self[key] = key 
...   return key 
... 
>>> d = MyDefaultDict() 
>>> d['joe'] 
'joe' 
>>> d 
{'joe': 'joe'} 
+2

¿Existe alguna razón específica para almacenar la clave además de devolverla? A menos que * necesite * saber qué claves fueron consultadas, no veo ninguna razón para hacer esto. –

+0

@JoachimSauer: Normalmente, uno espera que si 'd ['joe']' no genera un 'KeyError', entonces' 'joe' en d' se evalúa como 'True'. Si no guardé la clave, ese no sería el caso. – pillmuncher

+1

Pero esta solución hace que '' joe 'in d' evalúe a 'False' * a menos que * haya usado' d [' joe '] '* antes *. Entonces, el acceso puro de "solo lectura" cambia el resultado de * otro * acceso de solo lectura. No estoy seguro de que sea mejor. –

3

Es probable que deba escribir su propia clase que hereda de (o es similar a) defaultdict y anule el método __getitem__.

7

Editar: Vaya, me he dado cuenta de que el código en mi archivo de vino originalmente de otra Stackoverflow respuesta! https://stackoverflow.com/a/2912455/456876, vaya a votar ese.

Esto es lo que yo uso - es una variante defaultdict que pasa la clave como argumento para la función de fábrica valor predeterminado que se pasa como argumento a init, en lugar de argumentos:

class keybased_defaultdict(defaultdict): 
    def __missing__(self, key): 
     if self.default_factory is None: 
      raise KeyError(key) 
     else: 
      value = self[key] = self.default_factory(key) 
      return value 

este es el uso que desee:

>>> d = keybased_defaultdict(lambda x: x) 
>>> d[1] 
1 
>>> d['a'] 
'a' 

Otras posibilidades:

>>> d = keybased_defaultdict(lambda x: len(x)) 
>>> d['a'] 
1 
>>> d['abc'] 
3 
+2

De hecho, me sorprendió un poco descubrir que 'defaultdict' ya no funciona así ... –

+0

@pst Supongo que teóricamente tiene sentido que no sea el comportamiento predeterminado, si está almacenando la misma información en el clave y el valor, puede estar utilizando el tipo de datos incorrecto. Dicho esto, uso esto en mis programas en el trabajo. – weronika

4

Si no desea subclase dict, puede probar a usar

d.get('a', 'a') 
d.get('b', 'b') 
d.get('c', 'c') 

que creo que es más claro y menos mágico para este fin

Si usted es un fanático SECO y sólo tienen claves individuales de char , puede hacerlo :)

d.get(*'a'*2) 
d.get(*'b'*2) 
d.get(*'c'*2) 
Cuestiones relacionadas