¿Cómo puedo hacer que un valor predeterminado sea seguro para los clientes inesperados?

Varias veces (incluso varias seguidas) me ha mordido el error defaultdict: olvidar que algo es en realidad un valor predeterminado y tratarlo como un diccionario regular.

d = defaultdict(list) ... try: v = d["key"] except KeyError: print "Sorry, no dice!" 

Para aquellos que también han sido mordidos, el problema es evidente: cuando d no tiene una ‘clave’ clave, la v = d["key"] crea mágicamente una lista vacía y la asigna tanto a d["key"] como a v de plantear una excepción. Lo que puede ser bastante difícil de localizar si d proviene de algún módulo cuyos detalles no se recuerdan muy bien.

Estoy buscando una manera de eliminar la picadura de este error. Para mí, la mejor solución sería deshabilitar de alguna manera la magia de un punto predeterminado antes de devolverla al cliente.

Puede evitar la creación de valores predeterminados asignando d.default_factory = None . Sin embargo, no me gusta mucho la idea de que el objeto cambie repentinamente de comportamiento. Preferiría copiar valores al nuevo dict menos que imponga una penalización de rendimiento severa.

Aún puedes convertirlo a un dict normal.

 d = collections.defaultdict(list) d = dict(d) 

usar diferentes expresiones idiomáticas:

 if 'key' not in d: print "Sorry, no dice!" 

Ese es exactamente el comportamiento que desea de un valor defaultdict y no un error . Si no lo quieres, no uses un código predeterminado.

Si sigue olvidando qué tipo de variables tienen, entonces nómbrelas apropiadamente, por ejemplo, con el sufijo de los nombres de su defaultdict con “_ddict”.

Usando la idea de self.default_factory de restablecer self.default_factory , aquí hay una subclase intercambiable de defaultdict :

 class ToggleableDefaultdict(collections.defaultdict): def __init__(self,default_factory): self._default_factory=default_factory super(ToggleableDefaultdict,self).__init__(default_factory) def off(self): self.default_factory=None def on(self): self.default_factory=self._default_factory 

Por ejemplo:

 d=ToggleableDefaultdict(list) d['key'].append(1) print(d) # defaultdict(, {'key': [1]}) d.off() d['newkey'].append(2) # KeyError: 'newkey' d.on() d['newkey'].append(2) # defaultdict(, {'newkey': [2], 'key': [1]})