values keys item dictionaries create python dictionary

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