Использование ключа в collection.defaultdict
collections.defaultdict
отлично. Особенно в сочетании с lambda
:
>>> import collections
>>> a = collections.defaultdict(lambda : [None,None])
>>> a['foo']
[None, None]
Есть ли способ использовать указанный ключ (например, 'foo'
) в лямбда? Например (не работает):
>>> a = collections.defaultdict(lambda : [None]*key)
>>> a[1]
[None]
>>> a[2]
[None, None]
>>> a
defaultdict(<function <lambda> at 0x02984170>, {1: [None], 2: [None, None]})
Ответы
Ответ 1
Вероятно, вы хотите __missing__
, который вызывается при dict
всякий раз, когда вы пытаетесь получить доступ к элементу, отсутствующему в dict; ваниль __missing__
вызывает исключение, но вы можете делать все, что захотите, в подклассе:
class A(dict):
def __missing__(self, key):
value = self[key] = [None] * key
return value
Ответ 2
Объединив ответы SingleNegationElimination и rplnt, и документация defaultdict, я использовал следующее решение.
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]
Тело метода может быть просто return self.default_factory(key)
, но дополнительный код обязательно реплицирует все поведение defaultdict.
Использование, как описано в вопросе:
d = KeyBasedDefaultDict(lambda key: [None] * key)
d[1]
> [None]
d[2]
> [None, None]
Ответ 3
Это будет работать по запросу, хотя это, вероятно, не лучшее решение (вам нужно инициализировать его по умолчанию, а затем не использовать). Вероятно, это может быть исправлено с переопределением некоторых других методов.
class NoneDict(collections.defaultdict):
def __setitem__(self, key, value):
super(NoneDict, self).__setitem__(key, key*[None])