Mic*_*ior 75 python dictionary
我正在调试一些代码,我想知道何时访问特定的字典.好吧,它实际上是一个子类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)
Run Code Online (Sandbox Code Playgroud)
' name_label'是一个最终将设置的键,我想用它来识别输出.然后我改变了我正在修改的类DictWatch而不是dict更改了对超级构造函数的调用.但是,似乎没有任何事情发生.我以为我很聪明,但我想知道我是否应该走另一个方向.
谢谢您的帮助!
Mat*_*son 68
子类化的另一个问题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
Run Code Online (Sandbox Code Playgroud)
Bra*_*ore 32
你正在做什么绝对应该工作.我测试了你的课程,除了日志语句中缺少左括号外,它的工作正常.我能想到的只有两件事.首先,是否正确设置了日志语句的输出?您可能需要logging.basicConfig(level=logging.DEBUG)在脚本的顶部放置一个.
其次,__getitem__和__setitem__只在所谓的[]访问.因此,请确保您只访问DictWatch通过d[key],而不是d.get()和d.set()
这不应该真正改变结果(对于良好的日志记录阈值,这应该是有效的):你的init应该是:
def __init__(self,*args,**kwargs) : dict.__init__(self,*args,**kwargs)
Run Code Online (Sandbox Code Playgroud)
相反,因为如果用DictWatch([(1,2),(2,3)])或DictWatch(a = 1,b = 2)调用你的方法,这将失败.
(或者,更好的是,不要为此定义构造函数)
考虑子类化UserDict或UserList.这些类旨在被子类化,而正常dict和list不包含优化,并且包含优化.
正如安德鲁·佩特(Andrew Pate)的回答所提出的那样,子类化collections.UserDict而不是dict更不容易出错。
这是一个显示天真继承时出现问题的示例dict:
class MyDict(dict):\n\n def __setitem__(self, key, value):\n super().__setitem__(key, value * 10)\n\n\nd = MyDict(a=1, b=2) # Bad! MyDict.__setitem__ not called\nd.update(c=3) # Bad! MyDict.__setitem__ not called\nd[\'d\'] = 4 # Good!\nprint(d) # {\'a\': 1, \'b\': 2, \'c\': 3, \'d\': 40}\nRun Code Online (Sandbox Code Playgroud)\nUserDict继承自collections.abc.MutableMapping,因此这按预期工作:
class MyDict(collections.UserDict):\n\n def __setitem__(self, key, value):\n super().__setitem__(key, value * 10)\n\n\nd = MyDict(a=1, b=2) # Good: MyDict.__setitem__ correctly called\nd.update(c=3) # Good: MyDict.__setitem__ correctly called\nd[\'d\'] = 4 # Good\nprint(d) # {\'a\': 10, \'b\': 20, \'c\': 30, \'d\': 40}\nRun Code Online (Sandbox Code Playgroud)\n同样,你只需要实现__getitem__自动兼容key in my_dict, my_dict.get, \xe2\x80\xa6
注意: UserDict不是的子类dict,因此isinstance(UserDict(), dict)会失败(但isinstance(UserDict(), collections.abc.MutableMapping)会起作用)。
| 归档时间: |
|
| 查看次数: |
80568 次 |
| 最近记录: |