title: Difference between get and dunder getitem
body: <p>I am reading Fluent Python and trying to get a deeper understanding of dictionaries.</p>
  
  <p>So when I run the below, the results are easy to understand in that both get() and dunder getitem() return the same result</p>
  
  <pre><code>sample = {'a':1, 'b':2}
  print(sample.__getitem__('a')) # 1
  print(sample.get('a')) # 1
  </code></pre>
  
  <p>When I subclass dict with get(), I get a working instance</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Now if I replace get() with dunder getitem() I get an error and I am unsure why.</p>
  
  <pre><code>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'])
  </code></pre>
  
  <p>error</p>
  
  <pre><code>RecursionError: maximum recursion depth exceeded while calling a Python object
  </code></pre>
  
  <p>So the question is, what is the difference between get and dunder getitem in this situation and why does this cause a recursion error?</p>