Defaultdict: the first argument must be called or None

I ran the following code:

from collections import defaultdict lst = list(range(0,5)) d = defaultdict(lst) 

and I got this error:

 TypeError: first argument must be callable or None 

Please, help

+6
source share
3 answers

For defaultdict , the default value is usually not really a value , it is factory : a method that generates a new value. You can solve this problem using a lambda expression that generates a list:

 lst = lambda: list(range(0,5)) d = defaultdict(lst) 

This is also a good idea, because otherwise all default values will refer to the same list . For example, here:

 d[1].append(14) 

will not affect d[2] (since both d[1] and d[2] did not exist).

However, you can achieve this with

 val = list(range(0,5)) lst = lambda:val d = defaultdict(lst) 

But this can have undesirable side effects: if you execute d[1].append(14) , then d[2] will be [1,2,3,4,5,12] , and d[1] is d[2] will be True :

 $ python3 Python 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from collections import defaultdict >>> val = list(range(0,5)) >>> lst = lambda:val >>> d = defaultdict(lst) >>> d[1] [0, 1, 2, 3, 4] >>> d[1].append(14) >>> d[2] [0, 1, 2, 3, 4, 14] >>> d[1] is d[2] True 

then:

 $ python3 Python 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from collections import defaultdict >>> lst = lambda:list(range(0,5)) >>> d = defaultdict(lst) >>> d[1] [0, 1, 2, 3, 4] >>> d[1].append(14) >>> d[2] [0, 1, 2, 3, 4] >>> d[1] is d[2] False 
+9
source

You must make the parameter callable, say, with lambda :

 from collections import defaultdict d = defaultdict(lambda: list(range(0,5))) print(d[0]) # [0, 1, 2, 3, 4] 
+5
source

The default dictionary accepts the called as the first argument (which is the factory default for undefined values), so you should take the next step:

 from collections import defaultdict default_factory = (lambda: list(range(0,5)) d = defaultdict(default_factory) 

Learn more about calling in > What is "callable" in Python? Question SO.

+4
source

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


All Articles