Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 2 __missing__ method

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?

like image 685
SeasonalShot Avatar asked Jul 08 '16 07:07

SeasonalShot


People also ask

What is self __ dict __ Python?

__dict__ is A dictionary or other mapping object used to store an object's (writable) attributes. Or speaking in simple words every object in python has an attribute which is denoted by __dict__. And this object contains all attributes defined for the object.

What is the difference between Defaultdict and dict?

The difference is that a defaultdict will "default" a value if that key has not been set yet. If you didn't use a defaultdict you'd have to check to see if that key exists, and if it doesn't, set it to what you want. The lambda is defining a factory for the default value.

Is Defaultdict slower than dict?

defaultdict is faster for larger data sets with more homogenous key sets (ie, how short the dict is after adding elements);


1 Answers

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 a KeyError if key is not in the map.

If a subclass of dict defines a method __missing__() and key is not present, the d[key] operation calls that method with the key key as argument. The d[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
like image 142
Martijn Pieters Avatar answered Sep 17 '22 23:09

Martijn Pieters