python – 为什么重写__contains__会破坏OrderedDict.keys?
|
我正在继承OrderedDict(C python,2.7.3)来表示数据文件. __getitem__从数据文件中提取一个字段,并将其设置在当前实例上,类似于我在下面发布的代码.现在我想覆盖__contains__以返回True,如果该字段在字典中或磁盘上的文件中,因为它可以以任何方式读取.但是,这似乎打破了OrderedDict检查其密钥的能力. from collections import OrderedDict
dictclass = OrderedDict
class Foo(dictclass):
def __getitem__(self,key):
try:
return dictclass.__getitem__(self,key)
except KeyError:
pass
data = key*2
self[key] = data
return data
def __contains__(self,whatever):
return dictclass.__contains__(self,whatever) or 'bar' in whatever
a = Foo()
print a['bar']
print a.keys()
如果您运行上面的代码,您将获得此输出: barbar [] 请注意,如果您在上面的代码中更改dictclass = dict,它似乎仍然有效(给出以下输出). barbar ['bar'] 我做错了什么吗? 解决方法当Foo .__ contains__未定义时:a['bar'] 调用Foo .__ getitem__,执行 self[key] = data 这称为OrderedDict .__ setitem__,它以这种方式定义: def __setitem__(self,key,value,PREV=0,NEXT=1,dict_setitem=dict.__setitem__):
'od.__setitem__(i,y) <==> od[i]=y'
# Setting a new item creates a new link at the end of the linked list,# and the inherited dictionary is updated with the new key/value pair.
if key not in self:
root = self.__root
last = root[PREV]
last[NEXT] = root[PREV] = self.__map[key] = [last,root,key]
dict_setitem(self,value)
由于Foo .__ contains__未定义, if key not in self: 是真的.所以关键是正确添加到自我.__ root和self .__ map. 当Foo .__ contains__被定义时, if key not in self: 如果错.所以关键是没有正确添加到self .__ root和self .__ map. 我发现使用以下代码(在__setitem__和__iter__中添加print语句)很有帮助: from collections import OrderedDict
dictclass = OrderedDict
class Foo(dictclass):
def __getitem__(self,whatever):
print('contains: {}'.format(whatever))
return dictclass.__contains__(self,whatever) or 'bar' in whatever
def __setitem__(self,dict_setitem=dict.__setitem__):
'od.__setitem__(i,y) <==> od[i]=y'
# Setting a new item creates a new link at the end of the linked list,# and the inherited dictionary is updated with the new key/value pair.
print('key not in self: {}'.format(key not in self))
if key not in self:
root = self._OrderedDict__root
last = root[PREV]
last[NEXT] = root[PREV] = self._OrderedDict__map[key] = [last,key]
dict_setitem(self,value)
def __iter__(self):
'od.__iter__() <==> iter(od)'
# Traverse the linked list in order.
NEXT,KEY = 1,2
root = self._OrderedDict__root
curr = root[NEXT]
print('curr: {}'.format(curr))
print('root: {}'.format(root))
print('curr is not root: {}'.format(curr is not root))
while curr is not root:
yield curr[KEY]
curr = curr[NEXT]
a = Foo()
print a['bar']
# barbar
print a.keys()
# ['bar']
请注意,通过使Foo成为collections.MutableMapping的子类并将其大部分行为委托给OrderedDict属性,可以避免此问题: import collections
dictclass = collections.OrderedDict
class Foo(collections.MutableMapping):
def __init__(self,*args,**kwargs):
self._data = dictclass(*args,**kwargs)
def __setitem__(self,value):
self._data[key] = value
def __delitem__(self,key):
del self._data[key]
def __iter__(self):
return iter(self._data)
def __len__(self):
return len(self._data)
def __getitem__(self,key):
try:
return self._data[key]
except KeyError:
pass
data = key*2
self[key] = data
return data
def __contains__(self,whatever) or 'bar' in whatever
产量 a = Foo() print a['bar'] # barbar print a.keys() # ['bar'] 即使定义了__contains__. (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
