2012-01-05 13 views
10

Sto provando a creare una lista equivalente per l'utilissimo collections.defaultdict. Il seguente disegno funziona bene:creazione di una lista predefinita in 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) 

Ecco come lo si utilizza:

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

Cosa devo aggiungere alla defaultlist in modo da sostenere il seguente comportamento?

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

Questa domanda è un seguito a [questo] (http://stackoverflow.com/questions/8719558/defaultdict-equivalent-for-lists) – Jonathan

+0

Suppongo che tu stia solo cercando il metodo per sovraccaricare per l'accesso all'elemento (anziché per l'assegnazione dell'oggetto)? – delnan

+1

Non ha 'dl [2] = {'a', 1}' ha più senso? – FakeRainBrigand

risposta

17

Sull'esempio si dà, per la prima volta tenta di recuperare un non-esistente valore nella lista, come si fa dl[2]['a'], Python prima recuperare il terzo elemento (indice 2) nella lista, quindi procedere per ottenere l'elemento denominato 'a' su quell'oggetto - pertanto è necessario implementare il comportamento che si estende automaticamente al metodo __getitem__ così, in questo modo:

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

Esiste un pacchetto python disponibili:

$ pip install defaultlist 

Gli oggetti aggiunti sono riempiti con Nessuno per impostazione predefinita.

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

Fette e indicies negativi sono supportati allo stesso modo

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

funzioni factory semplici possono essere creati tramite lambda.

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

E 'anche possibile implementare funzioni avanzate di fabbrica:

>>> 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] 

Vedere la Documentation per ulteriori dettagli.