2011-11-01 9 views
15

collections.defaultdict es genial. Especialmente en conjunto con lambda:Usando la clave en collections.defaultdict

>>> import collections 
>>> a = collections.defaultdict(lambda : [None,None]) 
>>> a['foo'] 
[None, None] 

¿Hay una manera de utilizar la clave dada (por ejemplo 'foo') en el lambda? Por ejemplo (no funciona):

>>> a = collections.defaultdict(lambda : [None]*key) 
>>> a[1] 
[None] 
>>> a[2] 
[None, None] 
>>> a 
defaultdict(<function <lambda> at 0x02984170>, {1: [None], 2: [None, None]}) 

Respuesta

30

Es posible que desee __missing__ que se llama en dict cada vez que intente acceder a un elemento no está presente en el dict; la vainilla __missing__ genera una excepción, pero se puede hacer lo que quiera en una subclase:

class A(dict): 
    def __missing__(self, key): 
     value = self[key] = [None] * key 
     return value 
+0

no sabían acerca de este método magia antes, :), gran –

1

Esto funcionará conforme a lo solicitado, aunque no es probablemente la mejor solución (es necesario inicializarlo con llamada por defecto y luego no lo utiliza). Probablemente podría solucionarse anulando algunos otros métodos.

class NoneDict(collections.defaultdict): 
    def __setitem__(self, key, value): 
     super(NoneDict, self).__setitem__(key, key*[None]) 
2

La combinación de las respuestas de SingleNegationElimination y rplnt y the defaultdict documentation, he utilizado la siguiente solución.

import collections 
class KeyBasedDefaultDict(collections.defaultdict): 
    def __missing__(self, key): 
     if self.default_factory is None: 
      raise KeyError(key) 
     self[key] = self.default_factory(key) 
     return self[key] 

El cuerpo del método podría ser sólo return self.default_factory(key), pero el código adicional se asegura de replicar todo el comportamiento defaultdict.

Uso como se describe en la pregunta: ¿

d = KeyBasedDefaultDict(lambda key: [None] * key) 
d[1] 
> [None] 
d[2] 
> [None, None] 
Cuestiones relacionadas