If Foo.__contains__ is undefined :
a['bar']
calls Foo.__getitem__ , which executes
self[key] = data
This calls OrderedDict.__setitem__ , which is defined as follows:
def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__): 'od.__setitem__(i, y) <==> od[i]=y'
Since Foo.__contains__ is undefined,
if key not in self:
- it's true. Thus, the key is correctly added to the self.__root and self.__map .
When Foo.__contains__ is determined ,
if key not in self:
if false. Thus, the key is not appended properly to self.__root and self.__map . Foo.__contains__ Effective fools OrderedDict.__setitem__ in the thought that the key 'bar' has already been added.
I found it useful to play with the following code (adding print statements to __setitem__ and __iter__ ):
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): print('contains: {}'.format(whatever)) return dictclass.__contains__(self,whatever) or 'bar' in whatever def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__): 'od.__setitem__(i, y) <==> od[i]=y'
Note that you can avoid this problem by making Foo subclass of collections.MutableMapping and delegating most of your behavior to the OrderedDict attribute:
import collections dictclass = collections.OrderedDict class Foo(collections.MutableMapping): def __init__(self, *args, **kwargs): self._data = dictclass(*args, **kwargs) def __setitem__(self, key, 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): return dictclass.__contains__(self,whatever) or 'bar' in whatever
what gives
a = Foo() print a['bar']
even with __contains__ .