python - keys - Cómo subclasificar adecuadamente el dict y anular__getitem__ &__setitem__
python dictionary of dictionaries (5)
Estoy depurando algunos códigos y quiero saber cuándo se accede a un diccionario en particular. Bueno, en realidad es una clase que subclase dict
e implementa un par de características adicionales. De todos modos, lo que me gustaría hacer es subclasificarme y agregar anular __getitem__
y __setitem__
para producir algún resultado de depuración. En este momento, tengo
class DictWatch(dict):
def __init__(self, *args):
dict.__init__(self, args)
def __getitem__(self, key):
val = dict.__getitem__(self, key)
log.info("GET %s[''%s''] = %s" % str(dict.get(self, ''name_label'')), str(key), str(val)))
return val
def __setitem__(self, key, val):
log.info("SET %s[''%s''] = %s" % str(dict.get(self, ''name_label'')), str(key), str(val)))
dict.__setitem__(self, key, val)
'' name_label''
es una clave que eventualmente se establecerá y que quiero usar para identificar el resultado. Luego cambié la clase que estoy instrumentando a la subclase DictWatch
lugar de dict
y cambié la llamada al superconstructor. Aún así, nada parece estar sucediendo. Pensé que estaba siendo inteligente, pero me pregunto si debería ir en otra dirección.
¡Gracias por la ayuda!
Considere la posibilidad de subclasificar UserDict
o UserList
. Estas clases están destinadas a ser subclassed mientras que el dict
normal y la list
no son, y contienen optimizaciones.
Eso realmente no debería cambiar el resultado (que debería funcionar, para obtener buenos valores de umbral de registro): su init debería ser:
def __init__(self,*args,**kwargs) : dict.__init__(self,*args,**kwargs)
en cambio, porque si llamas a tu método con DictWatch ([(1,2), (2,3)]) o DictWatch (a = 1, b = 2), esto no funcionará.
(o, mejor, no defina un constructor para esto)
Lo que estás haciendo debería funcionar. Probé tu clase, y aparte de un paréntesis de apertura faltante en tus instrucciones de registro, funciona bien. Solo hay dos cosas en las que puedo pensar. Primero, ¿el resultado de su declaración de registro está configurado correctamente? Es posible que deba colocar un logging.basicConfig(level=logging.DEBUG)
en la parte superior de su script.
En segundo lugar, __getitem__
y __setitem__
solo se __setitem__
durante los accesos []
. Así que asegúrese de acceder solo a DictWatch
través de d[key]
, en lugar de d.get()
y d.set()
Otro problema cuando se subclasifica dict
es que el __init__
no llama a la update
, y la update
incorporada no llama a __setitem__
. Entonces, si quieres que todas las operaciones de setitem pasen por tu función __setitem__
, debes asegurarte de que se llame a ti mismo:
class DictWatch(dict):
def __init__(self, *args, **kwargs):
self.update(*args, **kwargs)
def __getitem__(self, key):
val = dict.__getitem__(self, key)
print ''GET'', key
return val
def __setitem__(self, key, val):
print ''SET'', key, val
dict.__setitem__(self, key, val)
def __repr__(self):
dictrepr = dict.__repr__(self)
return ''%s(%s)'' % (type(self).__name__, dictrepr)
def update(self, *args, **kwargs):
print ''update'', args, kwargs
for k, v in dict(*args, **kwargs).iteritems():
self[k] = v
Todo lo que debes hacer es
class BatchCollection(dict):
def __init__(self, inpt={}):
super(BatchCollection, self).__init__(inpt)
Un uso de muestra para mi uso personal
### EXAMPLE
class BatchCollection(dict):
def __init__(self, inpt={}):
super(BatchCollection, self).__init__(inpt)
def __setitem__(self, key, item):
if (isinstance(key, tuple) and len(key) == 2
and isinstance(item, collections.Iterable)):
# self.__dict__[key] = item
super(BatchCollection, self).__setitem__(key, item)
else:
raise Exception(
"Valid key should be a tuple (database_name, table_name) "
"and value should be iterable")
Nota : probado solo en python3