Une classe a un constructeur qui prend un paramètre:
class C(object):
def __init__(self, v):
self.v = v
...
Quelque part dans le code, il est utile que les valeurs d'un dict connaissent leurs clés.
Je veux utiliser un dict par défaut avec la clé passée aux valeurs par défaut du nouveau-né:
d = defaultdict(lambda : C(here_i_wish_the_key_to_be))
Aucune suggestion?
Il est à peine qualifié de intelligent - mais le sous-classement est votre ami:
class keydefaultdict(defaultdict):
def __missing__(self, key):
if self.default_factory is None:
raise KeyError( key )
else:
ret = self[key] = self.default_factory(key)
return ret
d = keydefaultdict(C)
d[x] # returns C(x)
Non, il n'y en a pas.
L'implémentation defaultdict
ne peut pas être configurée pour transmettre le key
manquant au default_factory
hors de la boîte. Votre seule option est d'implémenter votre propre sous-classe defaultdict
, comme suggéré par @JochenRitzel, ci-dessus.
Mais ce n'est pas "intelligent" ou presque aussi propre qu'une solution de bibliothèque standard (si elle existait). Ainsi, la réponse à votre question succincte, oui/non est clairement "Non".
Il est dommage que la bibliothèque standard manque un outil si fréquemment utilisé.
Je ne pense pas que vous ayez besoin de defaultdict
ici. Pourquoi ne pas simplement utiliser dict.setdefault
méthode?
>>> d = {}
>>> d.setdefault('p', C('p')).v
'p'
Cela créera bien sûr de nombreuses instances de C
. En cas de problème, je pense que l'approche plus simple fera l'affaire:
>>> d = {}
>>> if 'e' not in d: d['e'] = C('e')
Ce serait plus rapide que le defaultdict
ou toute autre alternative pour autant que je puisse voir.
ETA concernant la vitesse de in
test par rapport à la clause try-except:
>>> def g():
d = {}
if 'a' in d:
return d['a']
>>> timeit.timeit(g)
0.19638929363557622
>>> def f():
d = {}
try:
return d['a']
except KeyError:
return
>>> timeit.timeit(f)
0.6167065411074759
>>> def k():
d = {'a': 2}
if 'a' in d:
return d['a']
>>> timeit.timeit(k)
0.30074866358404506
>>> def p():
d = {'a': 2}
try:
return d['a']
except KeyError:
return
>>> timeit.timeit(p)
0.28588609450770264