title: How to access a superclass's class attributes in Python?
body: <p>Have a look at the following code:</p>
  
  <pre><code>class A(object):
      defaults = {'a': 1}
  
      def __getattr__(self, name):
          print('A.__getattr__')
          return self.get_default(name)
  
      @classmethod
      def get_default(cls, name):
          # some debug output
          print('A.get_default({}) - {}'.format(name, cls))
          try:
              print(super(cls, cls).defaults) # as expected
          except AttributeError: #except for the base object class, of course
              pass
  
          # the actual function body
          try:
              return cls.defaults[name]
          except KeyError:
              return super(cls, cls).get_default(name) # infinite recursion
              #return cls.__mro__[1].get_default(name) # this works, though
  
  class B(A):
      defaults = {'b': 2}
  
  class C(B):
      defaults = {'c': 3}
  
  
  c = C()
  print('c.a =', c.a)
  </code></pre>
  
  <p>I have a hierarchy of classes each with its own dictionary containing some default values. If an instance of a class doesn't have a particular attribute, a default value for it should be returned instead. If no default value for the attribute is contained in the current class's <code>defaults</code> dictionary, the superclass's <code>defaults</code> dictionary should be searched.</p>
  
  <p>I'm trying to implement this using the recursive class method <code>get_default</code>. The program gets stuck in an infinite recursion, unfortunately. My understanding of <code>super()</code> is obviously lacking. By accessing <code>__mro__</code>, I can get it to work properly though, but I'm not sure this is a proper solution.</p>
  
  <p>I have the feeling the answer is somewhere in <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=236275" rel="nofollow">this article</a>, but I haven't been able to find it yet. Perhaps I need to resort to using a metaclass?</p>
  
  <p><strong>edit:</strong> In my application, <code>__getattr__</code> first checks <code>self.base</code>. If it is not <code>None</code>, the attribute needs to be fetched from there. Only in the other case, a default value must be returned. I could probably override <code>__getattribute__</code>. Would that be the better solution?</p>
  
  <p><strong>edit 2:</strong> Below is an extended example of the functionality that I'm looking for. It is currently implemented using <code>__mro__</code> (unutbu's earlier suggestion, as opposed to my original recursive method). Unless someone can suggest a more elegant solution, I'm happy using this implementation. I hope this clears things up.</p>
  
  <pre><code>class A(object):
      defaults = {'a': 1}
  
      def __init__(self, name, base=None):
          self.name = name
          self.base = base
  
      def __repr__(self):
          return self.name
  
      def __getattr__(self, name):
          print(" '{}' attribute not present in '{}'".format(name, self))
          if self.base is not None:
              print("  getting '{}' from base ({})".format(name, self.base))
              return getattr(self.base, name)
          else:
              print("  base = None; returning default value")
              return self.get_default(name)
  
      def get_default(self, name):
          for cls in self.__class__.__mro__:
              try:
                  return cls.defaults[name]
              except KeyError:
                  pass
          raise KeyError
  
  class B(A):
      defaults = {'b': 2}
  
  class C(B):
      defaults = {'c': 3}
  
  
  c1 = C('c1')
  c1.b = 55
  
  print('c1.a = ...'); print('   ...', c1.a) # 1
  print(); print('c1.b = ...'); print('   ...', c1.b) # 55
  print(); print('c1.c = ...'); print('   ...', c1.c) # 3
  
  c2 = C('c2', base=c1)
  c2.c = 99
  
  print(); print('c2.a = ...'); print('   ...', c2.a) # 1
  print(); print('c2.b = ...'); print('   ...', c2.b) # 55
  print(); print('c2.c = ...'); print('   ...', c2.c) # 99
  </code></pre>
  
  <p>The output:</p>
  
  <pre><code>c1.a = ...
   'a' attribute not present in 'c1'
    base = None; returning default value
     ... 1
  
  c1.b = ...
     ... 55
  
  c1.c = ...
   'c' attribute not present in 'c1'
    base = None; returning default value
     ... 3
  
  c2.a = ...
   'a' attribute not present in 'c2'
    getting 'a' from base (c1)
   'a' attribute not present in 'c1'
    base = None; returning default value
     ... 1
  
  c2.b = ...
   'b' attribute not present in 'c2'
    getting 'b' from base (c1)
     ... 55
  
  c2.c = ...
     ... 99
  </code></pre>