defaultdict constant_factory没有按预期运行

时间:2013-08-07 16:31:36

标签: python factory defaultdict

我愿意将defaultdict ad hoc default_factory一起使用,这更符合我的目的。 default_factory[0,0]

我已经实现了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的工作做得非常好吗?

1 个答案:

答案 0 :(得分:4)

首先,只需使用:

defaultdict(lambda: [0, 0])

你相当精细的可调用性一遍又一遍地返回相同的列表。您在字典中使用所有值的相同列表。上面的lambda每次调用时都会返回一个 new 列表:

>>> 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

因此,您可以使用对一个列表的引用来填充您的字典,并且在一个列表中的值更改将反映在打印该列表的引用的任何位置。