2011-11-01 19 views
15

collections.defaultdict jest świetny. Zwłaszcza w połączeniu z lambda:Używanie klucza w kolekcjach.defaultdict

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

Czy istnieje sposób, aby użyć klawisza daną (np 'foo') w lambda? Na przykład (nie działa):

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

Odpowiedz

30

Prawdopodobnie chcesz __missing__ która jest wywoływana na dict gdy próby uzyskania dostępu element nie istnieje w dict; wanilia __missing__ podnosi wyjątek, ale można zrobić cokolwiek chcesz w podklasie:

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

nie wiedział o tym magicznym sposobem wcześniej :), wielki –

1

to będzie działać zgodnie z wnioskiem, chociaż to chyba nie jest najlepszym rozwiązaniem (trzeba go zainicjować rozmowy z domyślnej, a następnie go nie używać). Prawdopodobnie można to naprawić, zastępując inną metodę (metody).

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

Łącząc odpowiedź od SingleNegationElimination i rplnt i the defaultdict documentation użyłem następujące rozwiązanie.

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] 

Ciało metodą mogłoby być po prostu return self.default_factory(key), ale dodatkowy kod pilnuje replikować wszystkie zachowania defaultdict.

Wykorzystanie w sposób opisany w pytaniu:

d = KeyBasedDefaultDict(lambda key: [None] * key) 
d[1] 
> [None] 
d[2] 
> [None, None] 
Powiązane problemy