In [ ]:

The __missing__ method


In [1]:
class StrKeyDict0(dict):
    
    def __missing__(self, key):
        if isinstance(key, str):
            raise KeyError(key)
            
        return self[str(key)]
    
    def get(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            return default
        
    def __contains__(self, key):
        return key in self.keys() or str(key) in self.keys()

In [3]:
d = StrKeyDict0([('2', 'two'), ('4', 'four')])

In [4]:
d['2']


Out[4]:
'two'

In [5]:
d[4]


Out[5]:
'four'

In [6]:
d[1]


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-6-abe283337115> in <module>()
----> 1 d[1]

<ipython-input-1-e6e4506521a3> in __missing__(self, key)
      5             raise KeyError(key)
      6 
----> 7         return self[str(key)]
      8 
      9     def get(self, key, default=None):

<ipython-input-1-e6e4506521a3> in __missing__(self, key)
      3     def __missing__(self, key):
      4         if isinstance(key, str):
----> 5             raise KeyError(key)
      6 
      7         return self[str(key)]

KeyError: '1'

In [7]:
d['1']


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-7-e142bffca921> in <module>()
----> 1 d['1']

<ipython-input-1-e6e4506521a3> in __missing__(self, key)
      3     def __missing__(self, key):
      4         if isinstance(key, str):
----> 5             raise KeyError(key)
      6 
      7         return self[str(key)]

KeyError: '1'

In [8]:
d.get(2)


Out[8]:
'two'

In [9]:
d.get('2')


Out[9]:
'two'

In [10]:
d.get(1,'N/A')


Out[10]:
'N/A'

In [12]:
d.get('1', 'N/A')


Out[12]:
'N/A'

In [13]:
2 in d


Out[13]:
True

In [14]:
'2' in d


Out[14]:
True

UserDict


In [15]:
import collections

In [16]:
class StrKeyDict(collections.UserDict):
    
    def __missing__(self, key):
        if isinstance(key, str):
            raise KeyError(key)
            
        return self[str(key)]

    def __contains__(self, key):
        return str(key) in self.data
    
    def __setitem__(self, key, item):
        self.data[str(key)] = item

In [18]:
d = StrKeyDict([(2, 'two'), ('4', 'four')])

In [19]:
sorted(d.keys())


Out[19]:
['2', '4']

In [20]:
d[2], d['2']


Out[20]:
('two', 'two')

In [21]:
d[4], d['4']


Out[21]:
('four', 'four')

In [22]:
d['1']


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-22-e142bffca921> in <module>()
----> 1 d['1']

/anaconda3/lib/python3.6/collections/__init__.py in __getitem__(self, key)
    988             return self.data[key]
    989         if hasattr(self.__class__, "__missing__"):
--> 990             return self.__class__.__missing__(self, key)
    991         raise KeyError(key)
    992     def __setitem__(self, key, item): self.data[key] = item

<ipython-input-16-042d138b893e> in __missing__(self, key)
      3     def __missing__(self, key):
      4         if isinstance(key, str):
----> 5             raise KeyError(key)
      6 
      7         return self[str(key)]

KeyError: '1'

In [23]:
d.get('2'), d.get('4')


Out[23]:
('two', 'four')

In [25]:
d.get(1, 'N/A'), d.get('1', 'N/A')


Out[25]:
('N/A', 'N/A')

In [ ]: