Как правильно разделить на подклассы dict и переопределение __ getitem __ и __ setitem __

Я отлаживаю некоторый код, и я хочу узнать, когда к конкретному словарю получают доступ. Ну, это - на самом деле класс тот подкласс dict и реализации пара дополнительных функций. Так или иначе то, что я хотел бы сделать, разделить на подклассы dict самостоятельно и добавьте переопределение __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 и измененный вызов на суперконструктора. Однако, ничего, кажется, не происходит. Я думал, что был умен, но интересно, должен ли я идти другое направление.

Спасибо за справку!

75
задан martineau 30 January 2015 в 16:59
поделиться

3 ответа

То, что вы делаете, должно работать. Я протестировал ваш класс, и, за исключением отсутствующей открывающей скобки в ваших операторах журнала, он отлично работает. Я могу думать только о двух вещах. Во-первых, правильно ли настроен вывод вашего оператора журнала? Возможно, вам потребуется поместить logging.basicConfig (level = logging.DEBUG) в начало вашего скрипта.

Во-вторых, __ getitem __ и __ setitem __ вызываются только во время доступа [] . Поэтому убедитесь, что вы обращаетесь к DictWatch только через d [key] , а не через d.get () и d.set ()

32
ответ дан 24 November 2019 в 11:40
поделиться

Это не должно сильно изменить результат (который должен работать, при хороших значениях порога регистрации): ваш init должен быть :

def __init__(self,*args,**kwargs) : dict.__init__(self,*args,**kwargs) 

вместо этого, потому что если вы вызовете ваш метод с DictWatch([(1,2),(2,3)]) или DictWatch(a=1,b=2), это приведет к ошибке.

(или, лучше, не определяйте конструктор для этого)

9
ответ дан 24 November 2019 в 11:40
поделиться

Другая проблема при создании подкласса dict заключается в том, что встроенный __ init __ не вызывает 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
68
ответ дан 24 November 2019 в 11:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: