3

Как я могу получить фабрику с возможностью вызова для defaultdict, чтобы разрешить ее заполнение с пониманием? Я думаю, что это, вероятно, невозможно, но я не могу придумать, почему?Заполнение значения defaultdict во время инициализации

>>> def foo(*args): 
...  # TODO 
... 
>>> from collections import defaultdict 
>>> thing = foo(defaultdict, int) 
>>> d = thing((i, i*i) for i in range(3)) 
>>> d[2] 
# should return 4 
>>> d[-1] 
# should return 0 
+2

Я не понимаю, что вы пытаетесь сделать. Что такое 'thing' и' foo' и почему «вещь» возвращается 0? – jadkik94

+0

Чтобы уточнить: 'thing ((i, i * i) для i в диапазоне (3))' должен возвращать экземпляр 'defaultdict'. Я отредактирую вопрос, чтобы сделать это более ясным – wim

+0

О, хорошо, '-1' заставляло меня думать, что это список, а не отсутствующий индекс. Если бы вы хотели, чтобы «default_factory» сделал это, я не думаю, что это можно было бы сделать, потому что (из документов) «Завод по умолчанию называется *** без аргументов *** для создания нового значения, когда ключ нет, только в __getitem__. " – jadkik94

ответ

6

Любые аргументы defaultdict после default_factory трактуются так же, как аргументы dict:

>>> defaultdict(int, [(i, i*i) for i in range(5)]) 
defaultdict(<type 'int'>, {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}) 

Просто пройти понимание до defaultdict и дайте ему сделать работу:

def defaultdict_factory_factory(default_factory): 
    def defaultdict_factory(*args, **kwargs): 
     return defaultdict(default_factory, *args, **kwargs) 
    return defaultdict_factory 

Или используйте functools.partial:

def defaultdict_factory_factory(default_factory): 
    return partial(defaultdict, default_factory) 
+0

Очень приятно! Это отмечено в документах (http://docs.python.org/2/library/collections.html#collections.defaultdict), но не в 'help (defaultdict)' (по крайней мере, в моей установке Python 2.7) –

+0

Да на удивление отсутствует в docstring defaultdict. Интересно, сколько других секретов python скрывается там ... – wim

+0

Если это все еще отсутствует в docstring в 3.4b2, кто-то должен отправить отчет об ошибке. (Я предполагаю, что 'defaultdict' подвержен влиянию аргументальной клиники derby, поэтому вы не можете просто проверить последнюю версию 3.3.) – abarnert

5

Вы только что искали defaultdict.update?

>>> from collections import defaultdict 
>>> thing = defaultdict(int) 
>>> thing.update((i, i*i) for i in range(3)) 
>>> thing 
defaultdict(<type 'int'>, {0: 0, 1: 1, 2: 4}) 

Вы можете поместить это в функцию.

>>> def initdefaultdict(type_, *args, **kwargs): 
...  d = defaultdict(type_) 
...  d.update(*args, **kwargs) 
...  return d 
... 
>>> thing = initdefaultdict(int, ((i, i+10) for i in range(3))) 
>>> thing 
defaultdict(<type 'int'>, {0: 10, 1: 11, 2: 12}) 
>>> thing[3] 
0 

Или, чтобы удовлетворить ваши первоначальные требования, возвращать функцию:

>>> def defaultdictinitfactory(type_): # this is your "foo" 
...  def createupdate(*args, **kwargs): 
...    d = defaultdict(type_) 
...    d.update(*args, **kwargs) 
...    return d 
...  return createupdate 
... 
>>> f = defaultdictinitfactory(int) # f is your "thing" 
>>> d = f((i, i*i) for i in range(3)) 
>>> d 
defaultdict(<type 'int'>, {0: 0, 1: 1, 2: 4}) 
>>> 
+0

Это не пришло мне в голову. Если 'update' не вернул None, это почти сработало бы! – wim

+0

@wim Я думаю, что последнее обновление выполнит то, что вы хотите –