0

In the case of multiple inheritance in python, is there a way to identify which super class a class-level variable is obtained from?

All attempts I tried to google are overwhelmingly about How to get the attribute not find out where it came from:

https://www.google.com/search?q=pythin+which+super+class+defines+attr

https://www.google.com/search?q=python+which+super+class+has+attribute&oq=python+which+super+class+has+attr

https://www.google.com/search?q=python+which+super+class+attribute+obtained+from

I suppose I can manually step through the MRO using inspect.getmro(cls). But I couldn't find any more elegant solutions. Just wondering if anyone knows of one.

EDIT

For a concrete example:

class Super1(object):
    __class_attribute__ = "Foo"

class Super2(object):
    pass

class Derived(Super1, Super2):
    pass

d = Derived()

parent_cls = some_function_to_get_defining_class(d.__class_attribute__) # <-- should return `Super1`
ipetrik
  • 1,749
  • 18
  • 28
  • Possible duplicate of [python how to find which parent classes define methods of a child object](https://stackoverflow.com/questions/32895729/python-how-to-find-which-parent-classes-define-methods-of-a-child-object) – 001 Apr 21 '18 at 02:35
  • My mistake, @ipetrik, I though you were looking at methods, not class-level variables. – James Apr 21 '18 at 02:53
  • NP, @James. Sorry for not distinguishing. – ipetrik Apr 21 '18 at 02:54

1 Answers1

0

The __qualname__ attribute gives an indication from which class a method was inherited. However, this only returns a string, not the superclass itself. If you need to the superclass for metaprogramming, I think you are going to have to dig into the MRO.

class A:
    def a(self):
        return 1
    def b(self):
        return 2

class B:
    def b(self):
        return 2.5
    def c(self):
        return 3

class C(A,B):
    pass

Using:

C.b.__qualname__
# returns:
'A.b'

However, this does not apply when using abstract methods to define an interface, since the method has to be overwritten.

from abc import abstractmethod

class A:
    def a(self):
        return 1

    @abstractmethod
    def b(self):
        pass

class C(A):
    def b(self):
        return 100

C.b.__qualname__
# returns:
'C.b'
James
  • 32,991
  • 4
  • 47
  • 70