2011-11-01 9 views
15

collections.defaultdict è ottimo. Soprattutto in combinazione con lambda:Utilizzo della chiave in collections.defaultdict

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

C'è un modo per utilizzare la chiave di data (ad esempio 'foo') nella lambda? Per esempio (non funziona):

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

risposta

30

Probabilmente si desidera __missing__ che è chiamato a dict ogni volta che si tenta di accedere a un elemento non presente nella dict; la vaniglia __missing__ solleva un'eccezione, ma si potrebbe fare quello che ti piace in una sottoclasse:

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

non sapevano di questo metodo magico prima, :), grande –

1

questo funzionerà come richiesto, anche se non è probabilmente la soluzione migliore (è necessario inizializzare con la chiamata di default e poi lo si usa). Potrebbe probabilmente essere risolto con l'override di alcuni altri metodi.

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

Combinando le risposte da SingleNegationElimination e rplnt e the defaultdict documentation, ho usato la seguente soluzione.

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] 

Il corpo del metodo potrebbe essere solo return self.default_factory(key), ma il codice aggiuntivo si assicura di replicare tutti i comportamenti defaultdict.

Utilizzo come descritto nella domanda:

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