Как правильно подкласс dict и переопределить getitem & setitem
Я отлаживаю некоторый код, и я хочу узнать, когда конкретный словарь доступен. Ну, это на самом деле класс, подкласс dict и реализует несколько дополнительных функций. Во всяком случае, то, что я хотел бы сделать, это подкласс dict себя и добавить override __getitem__ и __setitem__ для получения некоторого отладочного вывода. Сейчас у меня
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' - это ключ, который в конечном итоге будет набор, который я хочу использовать для определения выхода. Затем я изменил класс я инструментирование в подкласс DictWatch вместо dict и изменил вызов суперконструктора. И все же, кажется, ничего не происходит. Я думал, что поступаю умно, но мне кажется, что я должен идти в другом направлении.
Спасибо за помощь!
5 ответов:
то, что вы делаете, должно абсолютно работать. Я проверил ваш класс, и помимо отсутствующей открывающей скобки в ваших заявлениях журнала, он работает просто отлично. Есть только две вещи, о которых я могу думать. Во-первых, правильно ли установлен вывод вашего оператора log? Возможно, вам придется поставить
logging.basicConfig(level=logging.DEBUG)в верхней части вашего скрипта.второе,
__getitem__и__setitem__вызываются только во время[]обращается. Поэтому убедитесь, что вы только доступDictWatchчерезd[key], а неd.get()иd.set()
еще одна проблема при создании подклассов
dictзаключается в том, что встроенный__init__не называетupdateи вupdateне называет__setitem__. Итак, если вы хотите, чтобы все операции setitem проходили через ваш__setitem__функция, вы должны убедиться, что она называется самостоятельно: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
это не должно действительно изменить результат (который должен работать, для хороших пороговых значений регистрации) : ваш init должно быть :
def __init__(self,*args,**kwargs) : dict.__init__(self,*args,**kwargs)вместо этого, потому что если вы вызываете свой метод с помощью DictWatch([(1,2),(2,3)]) или диктофон (a=1,b=2) это не удастся.
(или, лучше, не определяйте конструктор для этого)
рассмотрим подклассы
UserDictилиUserList. Эти классы предназначены для подклассов, тогда как нормальныйdictиlistне содержат оптимизаций.
все, что вам нужно сделать, это
class BatchCollection(dict): def __init__(self, inpt={}): super(BatchCollection, self).__init__(inpt)пример использования для моего личного использования
### 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")Примечание: тестируется только в python3