Defaultdict constant_factory does not behave as expected

I am ready to use defaultdict with ad hoc default_factory , which is better suited for my purpose. default_factory will be [0,0] .

I implemented the constant_factory function:

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

Then, when I try to use it, my defaultdict has unexpected behavior (at least I did not expect such behavior).

Here is an example:

 >>>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]}) 

Instead, I would like to get: 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]})

It seems that every time I am ready to increase the value of the first slot in the list corresponding to the i key, it increases all the values ​​of the first slots.

Since I'm pretty new to using defaultdict and method wrappers, can anyone explain to me what I'm doing wrong, since I believe Python is doing its job perfectly?

+1
source share
1 answer

First of all, just use:

 defaultdict(lambda: [0, 0]) 

Your rather complex caller returns the same list over and over. You use the same list for all values ​​in the dictionary. The above lambda returns a new list every time it is called:

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

Thus, you fill in your dictionary with links to one list, and a change in the values ​​in this list is reflected wherever a link to this one list is printed.

+4
source

Source: https://habr.com/ru/post/979802/


All Articles