defaultdict : first argument must be callable or None

前端 未结 3 1803
予麋鹿
予麋鹿 2020-12-18 19:55

I ran the following code :

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

and I got this error :

相关标签:
3条回答
  • 2020-12-18 20:39

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

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

    This is also a good idea here, since otherwise all default values would reference the same list. For instance here:

    d[1].append(14)
    

    will not have impact on d[2] (given both d[1] and d[2] did not exist).

    You can however achieve this with:

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

    But this can have unwanted side effects: if you here perform d[1].append(14) then d[2] will be [1,2,3,4,5,14] 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
    

    whereas:

    $ 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
    
    0 讨论(0)
  • 2020-12-18 20:40

    Default dictionary accepts callable as first argument(which is default factory for not defined values), so what you want to do is the next step:

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

    See more about callable in What is a "callable" in Python? SO question.

    0 讨论(0)
  • 2020-12-18 20:57

    You should make the parameter a callable, say, using lambda:

    from collections import defaultdict
    
    d = defaultdict(lambda: list(range(0,5)))
    print(d[0])
    # [0, 1, 2, 3, 4]
    
    0 讨论(0)
提交回复
热议问题