4

Given a class C with a function or method f, I use inspect.ismethod(obj.f) (where obj is an instance of C) to find out if f is bound method or not. Is there a way to do the same directly at the class level (without creating an object)?

inspect.ismethod does not work as this:

class C(object):

    @staticmethod
    def st(x):
        pass

    def me(self):
        pass

obj = C()

results in this (in Python 3):

>>> inspect.ismethod(C.st) 
False
>>> inspect.ismethod(C.me)
False
>>> inspect.ismethod(obj.st) 
False
>>> inspect.ismethod(obj.me)
True

I guess I need to check if the function/method is member of a class and not static but I was not able to do it easily. I guess it could be done using classify_class_attrs as shown here How would you determine where each property and method of a Python class is defined? but I was hoping there was another more direct way.

Community
  • 1
  • 1
Hernan
  • 5,811
  • 10
  • 51
  • 86

3 Answers3

5

There are no unbound methods in Python 3, so you cannot detect them either. All you have is regular functions. At most you can see if they have a qualified name with a dot, indicating that they are nested, and their first argument name is self:

if '.' in method.__qualname__ and inspect.getargspec(method).args[0] == 'self':
    # regular method. *Probably*

This of course fails entirely for static methods and nested functions that happen to have self as a first argument, as well as regular methods that do not use self as a first argument (flying in the face of convention).

For static methods and class methods, you'd have to look at the class dictionary instead:

>>> isinstance(vars(C)['st'], staticmethod)
True

That's because C.__dict__['st'] is the actual staticmethod instance, before binding to the class.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
0

Since inspect.ismethod returns True for both bound and unbound methods in Python 2.7 (ie., is broken), I'm using:

def is_bound_method(obj):
    return hasattr(obj, '__self__') and obj.__self__ is not None

It also works for methods of classes implemented in C, e.g., int:

>>> a = 1
>>> is_bound_method(a.__add__)
True
>>> is_bound_method(int.__add__)
False

But is not very useful in that case because inspect.getargspec does not work for functions implemented in C.

is_bound_method works unchanged in Python 3, but in Python 3, inspect.ismethod properly distinguishes between bound and unbound methods, so it is not necessary.

Greg Couch
  • 54
  • 2
  • This is only useful for Python **two**, while the question specifically asks about Python **three**, where there are no unbound methods. – Martijn Pieters Jan 05 '15 at 10:54
0

Could you use inspect.isroutine(...)? Running it with your class C I get:

>>> inspect.isroutine(C.st)
True
>>> inspect.isroutine(C.me)
True
>>> inspect.isroutine(obj.st)
True
>>> inspect.isroutine(obj.me)
True

Combining the results of inspect.isroutine(...) with the results of inspect.ismethod(...) may enable you to infer what you need to know.

Edit: dm03514's answer suggests you might also try inspect.isfunction():

>>> inspect.isfunction(obj.me)
False
>>> inspect.isfunction(obj.st)
True
>>> inspect.isfunction(C.st)
True
>>> inspect.isfunction(C.me)
False

Though as Hernan has pointed out, the results of inspect.isfunction(...) change in python 3.

srgerg
  • 18,719
  • 4
  • 57
  • 39