2013-08-07 1 views
1

Я желаю использовать defaultdict с ad hocdefault_factory, который лучше подходит для моей цели. default_factory будет [0,0].defaultdict constant_factory не ведет себя так, как ожидалось

Я реализовал constant_factory функцию:

def constant_factory(value): 
    return itertools.repeat(value).next 

Тогда, когда я пытаюсь использовать его, мой defaultdict имеет неожиданное поведение (по крайней мере, поведение я не ожидал).

Вот пример:

>>>import itertools 
>>>from collections import defaultdict 
>>>dictio=defaultdict(constant_factory([0,0])) 
>>>for i in xrange(10): 
... dictio[i][0]+=1 
>>>dictio 
defaultdict(<method-wrapper 'next' of itertools.repeat object at 0x000000000355FC50>, {0: [10, 0], 1: [10, 0], 2: [10, 0], 3: [10, 0], 4: [10, 0], 5: [10, 0], 6: [10, 0], 7: [10, 0], 8: [10, 0], 9: [10, 0]}) 

Вместо этого я хотел бы получить: defaultdict(<method-wrapper 'next' of itertools.repeat object at 0x000000000355FC50>, {0: [1, 0], 1: [1, 0], 2: [1, 0], 3: [1, 0], 4: [1, 0], 5: [1, 0], 6: [1, 0], 7: [1, 0], 8: [1, 0], 9: [1, 0]})

Кажется, что каждый раз, когда я хочу, чтобы увеличить значение первого слота списка соответствующий ключу i, он увеличивает все значения первых слотов.

Поскольку я довольно новичок в использовании defaultdict и обертки метода, кто-нибудь может объяснить мне, что я делаю неправильно, так как считаю, что Python делает свою работу отлично?

ответ

4

Прежде всего, просто использовать:

defaultdict(lambda: [0, 0]) 

Ваш скорее разработать с правом отзыва возвращает тот же список снова и снова. Вы используете тот же список для всех значений в своем словаре. Выше лямбда возвращает новый список каждый раз, когда она вызывается вместо:

>>> import itertools 
>>> lambda_default = lambda: [0, 0] 
>>> iter_default = itertools.repeat([0, 0]).next 
>>> lambda_default() is lambda_default() 
False 
>>> iter_default() is iter_default() 
True 

Вы таким образом заполнить свой словарь с ссылками на один список, и изменение значений в этом одном списке отражается везде ссылки на которые печатается один список.

+0

Спасибо, все ясно! Я прочитал документацию и нашел метод constant_factory, но я использовал ее, не понимая, как она работает. –