2012-01-05 25 views
10

Estoy tratando de crear una lista equivalente para el muy útil collections.defaultdict. El siguiente diseño funciona muy bien:creando una lista por defecto en python

class defaultlist(list): 
    def __init__(self, fx): 
     self._fx = fx 
    def __setitem__(self, index, value): 
     while len(self) <= index: 
      self.append(self._fx()) 
     list.__setitem__(self, index, value) 

Así es como usted lo utiliza:

>>> dl = defaultlist(lambda:'A') 
>>> dl[2]='B' 
>>> dl[4]='C' 
>>> dl 
['A', 'A', 'B', 'A', 'C'] 

¿Qué debo añadir a la defaultlist con el fin de apoyar el siguiente comportamiento?

>>> dl = defaultlist(dict) 
>>> dl[2]['a'] = 1 
>>> dl 
[{}, {}, {'a':1}] 
+0

Esta pregunta es una continuación de [este] (http://stackoverflow.com/questions/8719558/defaultdict-equivalent-for-lists) – Jonathan

+0

Supongo que solo está buscando el método para sobrecargar para el acceso al elemento (a diferencia de la asignación del elemento)? – delnan

+1

¿No sería 'dl [2] = {'a', 1}' tener más sentido? – FakeRainBrigand

Respuesta

17

En el ejemplo que se da, primero intente recuperar un valor que no existe en la lista, como lo hace dl[2]['a'], Python primero recuperar el tercer elemento (índice 2) en la lista, a continuación, proceder a obtener el elemento llamado 'a' en ese objeto - por lo tanto, se tienen que poner en práctica su comportamiento direccionamiento automático con el método __getitem__ así, como este:

class defaultlist(list): 
    def __init__(self, fx): 
     self._fx = fx 
    def _fill(self, index): 
     while len(self) <= index: 
      self.append(self._fx()) 
    def __setitem__(self, index, value): 
     self._fill(index) 
     list.__setitem__(self, index, value) 
    def __getitem__(self, index): 
     self._fill(index) 
     return list.__getitem__(self, index) 
1

Hay un paquete python disponibles:

$ pip install defaultlist 

Las indices agregadas se llenan con None por defecto.

>>> from defaultlist import defaultlist 
>>> l = defaultlist() 
>>> l 
[] 
>>> l[2] = "C" 
>>> l 
[None, None, 'C'] 
>>> l[4] 
>>> l 
[None, None, 'C', None, None] 

Rebanadas y negativos están soportados índices del mismo modo

>>> l[1:4] 
[None, 'C', None] 
>>> l[-3] 
'C' 

funciones simples de fábrica se pueden crear a través de lambda.

>>> l = defaultlist(lambda: 'empty') 
>>> l[2] = "C" 
>>> l[4] 
'empty' 
>>> l 
['empty', 'empty', 'C', 'empty', 'empty'] 

También es posible implementar funciones avanzadas de fábrica:

>>> def inc(): 
...  inc.counter += 1 
...  return inc.counter 
>>> inc.counter = -1 
>>> l = defaultlist(inc) 
>>> l[2] = "C" 
>>> l 
[0, 1, 'C'] 
>>> l[4] 
4 
>>> l 
[0, 1, 'C', 3, 4] 

Véase el Documentation para más detalles.

Cuestiones relacionadas