0

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.

ytjohn
  • 197
  • 1
  • 7

1 Answers1

2

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)

salparadise
  • 5,699
  • 1
  • 26
  • 32
  • This does seem to work. I had to change `class A:` to `class A(object):` in order to get the __mro__ attribute. – ytjohn Mar 21 '17 at 03:57
  • I also ran into the duplicate method you hinted at. It does the child method first, then prints the one in the parent method. Adding a break inside of `if f:` resolves that. – ytjohn Mar 21 '17 at 03:59