I am reading Fluent Python and trying to get a deeper understanding of dictionaries.
So when I run the below, the results are easy to understand in that both get() and dunder getitem() return the same result
sample = {'a':1, 'b':2}
print(sample.__getitem__('a')) # 1
print(sample.get('a')) # 1
When I subclass dict with get(), I get a working instance
class MyDict(dict):
def __missing__(self, key):
return 0
def get(self, key):
return self[key]
d = MyDict(sample)
print(d['a']) # 1
print(d['c']) # 0
Now if I replace get() with dunder getitem() I get an error and I am unsure why.
class MyDict2(dict):
def __missing__(self, key):
return 0
def __getitem__(self, key):
return self[key]
d = MyDict2(sample)
print(d['a'])
print(d['c'])
error
RecursionError: maximum recursion depth exceeded while calling a Python object
So the question is, what is the difference between get and dunder getitem in this situation and why does this cause a recursion error?
__getitem__ method is used to get an item from the invoked instances' attribute. __getitem__ is commonly used with containers like list, tuple, etc. __setitem__ method is used to set the item into a specific index of the invoked instances' attribute.
__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.
__setitem__ is a method used for assigning a value to an item. It is implicitly invoked when we set a value to an item of a list, dictionary, etc. __getitem__ is a method used for getting the value of an item. It is implicitly invoked when we access the items of a list, dictionary, etc.
in
def __getitem__(self, key):
return self[key]
self[key]
calls the lowest-level __getitem__
which calls self[key]
... infinite recursion.
In:
def get(self, key):
return self[key]
self[key]
calls the lowest-level __getitem__
as well but from the dict
class, so it doesn't recurse: it works (you just overloaded the get
method, that's all)
That is because self[key]
in MyDict2.__getitem__(key)
is equivalent to (i.e., calls) self.__getitem__(key)
=> infinite recursion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With