Search code examples
pythonflask-restful

how to get functions of parent classes python


How can I get the function of a parent class (as opposed to the unbound method)? In the example below, I would like to get the function and the doc string of the parent class. We have a list of methods (post, get) and there should be a matching function name within either the parent or child class. We need to get the function object and see its attributes. For the child class, this is easy, but I don't see how to do it for the parent class.

I've simplified the example below, but in our more complex case, we have a large flask app that we rewrote to use a common set of base/parent classes (with decorated functions). Our third party library uses __dict__.get to generate swagger documentation.

class A():

    def get(self):
        """geta"""
        desc = 'geta'
        print('got it')


class B(A):

    def post(self):
        """postb"""
        desc = 'postb'
        print('posted')


# this is the part we need to change:
methods = ['post', 'get']
for method in methods:
    f = B.__dict__.get(method, None)
    print(f)
    print(f.__doc__)

The results will be:

<function post at 0x1054f96e0>
postb
None
None

I have an idea of iterating B.bases looking for matching method names. I am worried about a long and deep set of nested if and for loops, and am hoping for a more pythonic and clean solution. dir(B) lists all of the functions, but i don't know how to grab a function except through the dict.


Solution

  • You can use the class __mro__ magic method:

    In [3]: class A:  #(object) if using 2.x
       ...:     def post(s):
       ...:         """foo"""
       ...:         pass
       ...:
       ...:
    
    In [4]: class B(A):
       ...:     def get(s):
       ...:         """boo"""
       ...:         pass
       ...:
    
    In [8]: methods = ['get', 'post']
    
    
    In [10]: for m in methods:
        ...:     for c in B.__mro__:
        ...:         f = c.__dict__.get(m)
        ...:         if f:
        ...:             print(f)
        ...:             print(f.__doc__)
                         break # if you don't want duplicate functions
                               # (with subclass listed first)
        ...:
    <function B.get at 0x102ece378>
    boo
    <function A.post at 0x102ee8730>
    foo
    

    However, this may print the function twice if one of your subclasses is overriding a method from its parent (not sure if you care or it is what you want)