Issue
I wrote a very simple program to subclass a dictionary. I wanted to try the __missing__
method in python.
After some research i found out that in Python 2 it's available in defaultdict
. ( In python 3 we use collections.UserDict though..)
The __getitem__
is the on responsible for calling the __missing__
method if the key isn't found.
When i implement __getitem__
in the following program i get a key error, but when i implement without it, i get the desired value.
import collections
class DictSubclass(collections.defaultdict):
def __init__(self,dic):
if dic is None:
self.data = None
else:
self.data = dic
def __setitem__(self,key,value):
self.data[key] = value
########################
def __getitem__(self,key):
return self.data[key]
########################
def __missing__(self,key):
self.data[key] = None
dic = {'a':4,'b':10}
d1 = DictSubclass(dic)
d2 = DictSubclass(None)
print d1[2]
I thought i needed to implement __getitem__
since it's responsible for calling __missing__
. I understand that the class definition of defaultdict has a __getitem__
method. But even so, say i wanted to write my own __getitem__
, how would i do it?
Solution
The dict
type will always try to call __missing__
. All that defaultdict
does is provide an implementation; if you are providing your own __missing__
method you don't have to subclass defaultdict
at all.
See the dict
documentation:
d[key]
Return the item of d with key key. Raises aKeyError
if key is not in the map.If a subclass of dict defines a method
__missing__()
and key is not present, thed[key]
operation calls that method with the key key as argument. Thed[key]
operation then returns or raises whatever is returned or raised by the__missing__(key)
call. No other operations or methods invoke__missing__()
.
However, you need to leave the default __getitem__
method in place, or at least call it. If you override dict.__getitem__
with your own version and not call the base implementation, __missing__
is never called.
You could call __missing__
from your own implementation:
def __getitem__(self, key):
if key not in self.data:
return self.__missing__(key)
return self.data[key]
or you could call the original implementation:
def __getitem__(self, key):
if key not in self.data:
return super(DictSubclass , self).__getitem__(key)
return self.data[key]
In Python 2, you can just subclass UserDict.UserDict
:
from UserDict import UserDict
class DictSubclass(UserDict):
def __missing__(self, key):
self.data[key] = None
Answered By - Martijn Pieters
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.