Search code examples
pythoninheritanceintrospection

In Python, class from which a given instance is inheriting a particular method


I know that in Python, given a class ClassA, with

inspect.getmembers(ClassA, predicate=inspect.ismethod)

I can iterate over the different methods present in ClassA. Inherited methods are also gathered, which is convenient in my case. But what I would need is, given a particular method method1 of ClassA, to get the class from which ClassA inherited method1. It might be ClassA itself, or any of its parents/grandparents. I thought I could recursively traverse the __bases__ attribute, looking for the method1 attribute at each step. But maybe this functionality is already implemented somewhere. Is there another way?


Solution

  • Look through the MRO (Method Resolution Order), using inspect.getmro() (which works on both old and new-style classes):

    def class_for_method(cls, method):
        return next((c for c in inspect.getmro(cls) 
                     if method.__func__ in vars(c).values()), None)
    

    There is currently no stdlib method to do this search for you, no.

    Demo:

    >>> import inspect
    >>> def class_for_method(cls, method):
    ...     return next((c for c in inspect.getmro(cls) 
    ...                  if method.__func__ in vars(c).values()), None)
    ... 
    >>> class Base1(object):
    ...     def foo(self): pass
    ... 
    >>> class Base2(object):
    ...     pass
    ... 
    >>> class ClassA(Base1, Base2):
    ...     pass
    ... 
    >>> class_for_method(ClassA, ClassA.foo)
    <class '__main__.Base1'>
    

    If no base class is found, the above expression returns None:

    >>> class Bar:
    ...     def spam(): pass
    ... 
    >>> class_for_method(ClassA, Bar.spam) is None
    True