I had this problem at work today. I had this snippet of Python code:
KeyError. I inspected and I was inside an
OrderedDict subclass, so inside the
pop() method implementation I had this code:
if key in self: del self[key]
Which was the originator of the exception raised. Took me a while to find out what the problem was until I noticed that the instance I was working on was not operating on the class where the
pop() call was made, but on a subclass that reimplemented
__getitem__. This made me open my eyes and spot the error.
This was my situation. I was looking at the code inside the
delete_key method, which is defined under
MyBaseDict, but I was on an instance of
MyOtherDict. Look at the following code:
class MyBaseDict(dict): def delete_key(self, key): del self[key] class MyOtherDict(MyBaseDict): def __init__(self, base, *args, **kwargs): self.base = base super(MyOtherDict, self).__init__(*args, **kwargs) def __getitem__(self, key): return self.base[key] my_od = MyBaseOd() my_od['a'] = 1 my_od['b'] = 2 assert my_od['b'] == 2 other_od = MyOtherOd(my_od) assert other_od['b'] == 2 del other_od['b'] # Raises KeyError
At first sight it makes no sense that after I asserted that the key
'b' exists I get a
KeyError trying to delete it! But what is happening is that the
del statement is calling an internal implementation of the base class, dict in this case. Which attempts to use an internal implementation of
__getdict__ and not the user defined one.
The proper way to make a subclass of dict in Python requires you to subclass collections.MutableMapping. That will ensure that your
del statement uses the user defined dict protocol methods.
from collections import MutableMapping class MyBaseDict(MutableMapping): ....
With the original inheritance change from dict to
MutableMapping the above script now works.