Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a function is a method of some object

How to check if a function is a method of some object?

For example:

def check_method(f):
    ...

check_method(lambda x: x + 1)           # >>> False
check_method(SomeClass().some_method)  # >>> True

There are some special attributes in methods in my 'helloworld' example (e.g. 'im_self', '__self__' etc). Can I rely on them or there is some nicer way?

like image 553
Roman Bodnarchuk Avatar asked May 11 '11 11:05

Roman Bodnarchuk


3 Answers

Use inspect.ismethod().

The documentation states:

Return true if the object is a bound method written in Python.

This means that it will work as you intend for classes that you define in Python. However, for methods of built-in classes like list or classes implemented in extension modules it will return False.

like image 133
David Heffernan Avatar answered Oct 14 '22 00:10

David Heffernan


It is also possible to check against the types defined in the built in types library:

import types
isinstance(obj.method, types.MethodType) # True
like image 5
Rovanion Avatar answered Oct 13 '22 22:10

Rovanion


A twist to the question involves asking to check if some function name would be available as a method. Since duck typing is considered pythonic there should be a simple

hasmethod(obj, 'some_method')

but it seems, there isn't.

Duck typing seems to be best done by just trying:

try:
  obj.some_method()
except:
  # try something else

If someone wants a function to check programmatically if an object has a method with a certain variable name, then the following function has been mentioned:

def hasmethod(obj, method_name):
  return hasattr(obj, method_name) and callable(getattr(obj, method_name))

But for Python 3 and 3.1 at least you need to get callable() back which was removed. A discussion of the want of bringing it back can be found in a python bug entry Resurrect callable with e.g.:

def callable(obj):
    return isinstance(obj, collections.Callable) 

This is straight from the above mentioned python bugtracker. Other sources on stackoverflow mention

callable = lambda o: hasattr(o, '__call__') or isinstance(o, collections.Callable)

which adds the hasattr to the call. Both work fine in my use case

>>> bstr = b'spam'
>>> str = 'eggs'
>>> hasmethod(str, 'decode')
False
>>> hasmethod(bstr, 'decode')
True

For more details look at the already cited other question

like image 2
cfi Avatar answered Oct 13 '22 22:10

cfi