web-dev-qa-db-fra.com

defaultdict: le premier argument doit être appelable ou Aucun

J'ai exécuté le code suivant:

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

et j'ai eu cette erreur:

TypeError: first argument must be callable or None

Veuillez aider

12
Arcyno

Pour un defaultdict le valeur par défaut est généralement pas vraiment une valeur, c'est un sine: une méthode qui génère une nouvelle valeur . Vous pouvez résoudre ce problème en utilisant une expression lambda qui génère une liste:

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

C'est aussi une bonne idée ici, car sinon toutes les valeurs par défaut serait référence à la même liste. Par exemple ici:

d[1].append(14)

pas aura un impact sur d[2] (étant donné que d[1] et d[2] n'existaient pas).

Vous pouvez cependant y parvenir avec:

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

Mais cela peut avoir des effets secondaires indésirables: si vous effectuez ici d[1].append(14) alors d[2] Sera [1,2,3,4,5,14] Et d[1] is d[2] Sera 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

tandis que:

$ 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
15
Willem Van Onsem

Vous devriez faire du paramètre un appelable, disons, en utilisant lambda:

from collections import defaultdict

d = defaultdict(lambda: list(range(0,5)))
print(d[0])
# [0, 1, 2, 3, 4]
6
Moses Koledoye

Dictionnaire par défaut accepte l'appelable comme premier argument (qui est la fabrique par défaut pour les valeurs non définies), donc ce que vous voulez faire est l'étape suivante:

from collections import defaultdict


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

En savoir plus sur callable dans Qu'est-ce qu'un "callable" en Python? SO question.

4
Andriy Ivaneyko