如何正确的inheritancedict并覆盖__getitem__&__setitem__
我正在debugging一些代码,我想知道什么时候访问一个特定的字典。 那么,它实际上是一个子类dict
并实现了一些额外的function。 无论如何,我想要做的是自己的子类dict
并添加覆盖__getitem__
和__setitem__
产生一些debugging输出。 现在,我有
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'
是最终将被设置,我想用来确定输出的关键。 然后我改变了我正在testing的类DictWatch
代替DictWatch
而不是dict
并且改变了对superconstructor的调用。 但是,似乎没有任何事情发生。 我以为我很聪明,但我想知道我是否应该走向一个不同的方向。
谢谢您的帮助!
你在做什么应该绝对工作。 我testing了你的类,除了在你的日志语句中缺less左括号,它工作得很好。 我只能想到两件事情。 首先,您的日志语句的输出设置是否正确? 您可能需要在脚本的顶部放置一个logging.basicConfig(level=logging.DEBUG)
。
其次, __getitem__
和__setitem__
仅在[]
访问期间被调用。 所以确保你只通过d[key]
而不是d.get()
和d.set()
访问DictWatch
子类化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
这应该不会真的改变结果(这应该工作,为了良好的日志logging阈值):你的init应该是:
def __init__(self,*args,**kwargs) : dict.__init__(self,*args,**kwargs)
相反,因为如果你用DictWatch([(1,2),(2,3)])或DictWatch(a = 1,b = 2)调用你的方法,这将失败。
(或者,更好的是,不要为此定义一个构造函数)
你所要做的就是
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中进行testing