title: How can we force getattribute() to be called for magic methods (special methods)?
body: <p>The <a href="https://docs.python.org/2/reference/datamodel.html#new-style-special-lookup" rel="noreferrer">python documentation</a> states that <code>__getattribute__</code> may be bypassed when looking up special methods. This is the result of implicit invocation via language syntax or built-in functions.</p>
  
  <p>For example, </p>
  
  <pre><code>elem = container[0]
  </code></pre>
  
  <p>is not the same as:</p>
  
  <pre><code>elem = container.__getattribute__('__getitem__')[0]
  </code></pre>
  
  <p>Below is a another example:</p>
  
  <pre><code>class WrappedList:
      def __init__(self):
          object.__setattr__(self, 'interal_list', ['apple', 'pear', 'orange'])
  
      def __getattribute__(self, attr_name):
          interal_list = object.__getattribute__(self, 'interal_list')
          attr = getattr(interal_list, attr_name)
          return attr
  
  wl = WrappedList()
  
  print("\nSTART TEST 01 ------------------------")
  try:
      print(wl[0]) # throws TypeError: 'WrappedList' object does not support indexing
  except TypeError as e:
      print(e)
  
  print("\nSTART TEST 02 ------------------------")
  try:
      getitem = getattr(wl, '__getitem__')
      print(getitem(0)) # works just fine
  except TypeError as e:
      print(e)
  </code></pre>
  
  <p>I would like to write a class named something like <code>MagicOverrider</code> where any class which inherits from <code>MagicOverrider</code> <strong>always</strong> calls <code>__getattribute__</code>, instead of going around it. My question is how can we do this?</p>
  
  <p>I tried the following:</p>
  
  <pre><code>class MagicOverrider:
  
      def __call__(self, *args, **kwargs):
          f = getattr(self, '__call__')
          return f(*args, **kwargs)
  
      def __iter__(self, *args, **kwargs):
          f = getattr(self, '__iter__')
          return f(*args, **kwargs)
  
      def __getitem__(self, *args, **kwargs):
          f = getattr(self, '__getitem__')
          return f(*args, **kwargs)
  
      def __setitem__(self, *args, **kwargs):
          f = getattr(self, '__setitem__')
          return f(*args, **kwargs)
  
      def __add__(self, *args, **kwargs):
          f = getattr(self, '__add__')
          return f(*args, **kwargs)
  
      def __sub__(self, *args, **kwargs):
          f = getattr(self, '__sub__')
          return f(*args, **kwargs)
  
      def __mul__(self, *args, **kwargs):
          f = getattr(self, '__mul__')
          return f(*args, **kwargs)
  
      def __truediv__(self, *args, **kwargs):
          f = getattr(self, '__truediv__')
          return f(*args, **kwargs)
  
      def __floordiv__(self, *args, **kwargs):
          f = getattr(self, '__floordiv__')
          return f(*args, **kwargs)
  
      def __mod__(self, *args, **kwargs):
          f = getattr(self, '__mod__')
          return f(*args, **kwargs)
  
      def __divmod__(self, *args, **kwargs):
          f = getattr(self, '__divmod__')
          return f(*args, **kwargs)
  
      def __pow__(self, *args, **kwargs):
          f = getattr(self, '__pow__')
          return f(*args, **kwargs)
  
      def __lshift__(self, *args, **kwargs):
          f = getattr(self, '__lshift__')
          return f(*args, **kwargs)
  
      def __rshift__(self, *args, **kwargs):
          f = getattr(self, '__rshift__')
          return f(*args, **kwargs)
  
      def __and__(self, *args, **kwargs):
          f = getattr(self, '__and__')
          return f(*args, **kwargs)
  
      def __xor__(self, *args, **kwargs):
          f = getattr(self, '__xor__')
          return f(*args, **kwargs)
  
      def __or__(self, *args, **kwargs):
          f = getattr(self, '__or__')
          return f(*args, **kwargs)
  
      def __radd__(self, *args, **kwargs):
          f = getattr(self, '__radd__')
          return f(*args, **kwargs)
  
      def __rsub__(self, *args, **kwargs):
          f = getattr(self, '__rsub__')
          return f(*args, **kwargs)
  
      def __rmul__(self, *args, **kwargs):
          f = getattr(self, '__rmul__')
          return f(*args, **kwargs)
  
      def __rtruediv__(self, *args, **kwargs):
          f = getattr(self, '__rtruediv__')
          return f(*args, **kwargs)
  
      def __rfloordiv__(self, *args, **kwargs):
          f = getattr(self, '__rfloordiv__')
          return f(*args, **kwargs)
  
      def __rmod__(self, *args, **kwargs):
          f = getattr(self, '__rmod__')
          return f(*args, **kwargs)
  
      def __rdivmod__(self, *args, **kwargs):
          f = getattr(self, '__rdivmod__')
          return f(*args, **kwargs)
  
      def __rpow__(self, *args, **kwargs):
          f = getattr(self, '__rpow__')
          return f(*args, **kwargs)
  
      def __rlshift__(self, *args, **kwargs):
          f = getattr(self, '__rlshift__')
          return f(*args, **kwargs)
  
      def __rrshift__(self, *args, **kwargs):
          f = getattr(self, '__rrshift__')
          return f(*args, **kwargs)
  
      def __rand__(self, *args, **kwargs):
          f = getattr(self, '__rand__')
          return f(*args, **kwargs)
  
      def __rxor__(self, *args, **kwargs):
          f = getattr(self, '__rxor__')
          return f(*args, **kwargs)
  
      def __neg__(self, *args, **kwargs):
          f = getattr(self, '__neg__')
          return f(*args, **kwargs)
  
      def __pos__(self, *args, **kwargs):
          f = getattr(self, '__pos__')
          return f(*args, **kwargs)
  
      def __abs__(self, *args, **kwargs):
          f = getattr(self, '__abs__')
          return f(*args, **kwargs)
  
      def __invert__(self, *args, **kwargs):
          f = getattr(self, '__invert__')
          return f(*args, **kwargs)
  
      def __complex__(self, *args, **kwargs):
          f = getattr(self, '__complex__')
          return f(*args, **kwargs)
  
      def __int__(self, *args, **kwargs):
          f = getattr(self, '__int__')
          return f(*args, **kwargs)
  
      def __float__(self, *args, **kwargs):
          f = getattr(self, '__float__')
          return f(*args, **kwargs)
  
      def __round__(self, *args, **kwargs):
          f = getattr(self, '__round__')
          return f(*args, **kwargs)
  
      def __index__(self, *args, **kwargs):
          f = getattr(self, '__index__')
          return f(*args, **kwargs)
  
      def __eq__(self, *args, **kwargs):
          f = getattr(self, '__eq__')
          return f(*args, **kwargs)
  
      def __ne__(self, *args, **kwargs):
          f = getattr(self, '__ne__')
          return f(*args, **kwargs)
  
      def __lt__(self, *args, **kwargs):
          f = getattr(self, '__lt__')
          return f(*args, **kwargs)
  
      def __le__(self, *args, **kwargs):
          f = getattr(self, '__le__')
          return f(*args, **kwargs)
  
      def __gt__(self, *args, **kwargs):
          f = getattr(self, '__gt__')
          return f(*args, **kwargs)
  
      def __ge__(self, *args, **kwargs):
          f = getattr(self, '__ge__')
          return f(*args, **kwargs)
  
      def __bool__(self, *args, **kwargs):
          f = getattr(self, '__bool__')
          return f(*args, **kwargs)
  
      def __new__(self, *args, **kwargs):
          f = getattr(self, '__new__')
          return f(*args, **kwargs)
  
      def __del__(self, *args, **kwargs):
          f = getattr(self, '__del__')
          return f(*args, **kwargs)
  
      def __slots__(self, *args, **kwargs):
          f = getattr(self, '__slots__')
          return f(*args, **kwargs)
  
      def __hash__(self, *args, **kwargs):
          f = getattr(self, '__hash__')
          return f(*args, **kwargs)
  
      def __instancecheck__(self, *args, **kwargs):
          f = getattr(self, '__instancecheck__')
          return f(*args, **kwargs)
  
      def __subclasscheck__(self, *args, **kwargs):
          f = getattr(self, '__subclasscheck__')
          return f(*args, **kwargs)
  
      def __subclasshook__(self, *args, **kwargs):
          f = getattr(self, '__subclasshook__')
          return f(*args, **kwargs)
  
      def __ror__(self, *args, **kwargs):
          f = getattr(self, '__ror__')
          return f(*args, **kwargs)
  
      def __iadd__(self, *args, **kwargs):
          f = getattr(self, '__iadd__')
          return f(*args, **kwargs)
  
      def __isub__(self, *args, **kwargs):
          f = getattr(self, '__isub__')
          return f(*args, **kwargs)
  
      def __imul__(self, *args, **kwargs):
          f = getattr(self, '__imul__')
          return f(*args, **kwargs)
  
      def __itruediv__(self, *args, **kwargs):
          f = getattr(self, '__itruediv__')
          return f(*args, **kwargs)
  
      def __ifloordiv__(self, *args, **kwargs):
          f = getattr(self, '__ifloordiv__')
          return f(*args, **kwargs)
  
      def __imod__(self, *args, **kwargs):
          f = getattr(self, '__imod__')
          return f(*args, **kwargs)
  
      def __ipow__(self, *args, **kwargs):
          f = getattr(self, '__ipow__')
          return f(*args, **kwargs)
  
      def __ilshift__(self, *args, **kwargs):
          f = getattr(self, '__ilshift__')
          return f(*args, **kwargs)
  
      def __irshift__(self, *args, **kwargs):
          f = getattr(self, '__irshift__')
          return f(*args, **kwargs)
  
      def __iand__(self, *args, **kwargs):
          f = getattr(self, '__iand__')
          return f(*args, **kwargs)
  
      def __ixor__(self, *args, **kwargs):
          f = getattr(self, '__ixor__')
          return f(*args, **kwargs)
  
      def __repr__(self, *args, **kwargs):
          f = getattr(self, '__repr__')
          return f(*args, **kwargs)
  
      def __str__(self, *args, **kwargs):
          f = getattr(self, '__str__')
          return f(*args, **kwargs)
  
      def __cmp__(self, *args, **kwargs):
          f = getattr(self, '__cmp__')
          return f(*args, **kwargs)
  
      def __rcmp__(self, *args, **kwargs):
          f = getattr(self, '__rcmp__')
          return f(*args, **kwargs)
  
      def __nonzero__(self, *args, **kwargs):
          f = getattr(self, '__nonzero__')
          return f(*args, **kwargs)
  
      def __unicode__(self, *args, **kwargs):
          f = getattr(self, '__unicode__')
          return f(*args, **kwargs)
  </code></pre>
  
  <p>However, my solution has at least two problems:</p>
  
  <ul>
  <li>It won't work anymore if new magic methods are introduced in a future release of python</li>
  <li>the first line, <code>class MagicOverrider:</code>, throws <code>TypeError: 'function' object is not iterable</code></li>
  </ul>