Как правильно подкласс 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