How do you check whether a python method is bound or not?

Question:

Given a reference to a method, is there a way to check whether the method is bound to an object or not? Can you also access the instance that it’s bound to?

Asked By: readonly

||

Answers:

im_self attribute (only Python 2)

Answered By: Mark Cidade
def isbound(method):
    return method.im_self is not None
    
def instance(bounded_method):
    return bounded_method.im_self

User-defined methods:

When a user-defined method object is
created by retrieving a user-defined
function object from a class, its
im_self attribute is None and the
method object is said to be unbound.
When one is created by retrieving a
user-defined function object from a
class via one of its instances, its
im_self attribute is the instance, and
the method object is said to be bound.
In either case, the new method’s
im_class attribute is the class from
which the retrieval takes place, and
its im_func attribute is the original
function object.

In Python 2.6 and 3.0:

Instance method objects have new
attributes for the object and function
comprising the method; the new synonym
for im_self is __self__, and im_func
is also available as __func__. The old
names are still supported in Python
2.6, but are gone in 3.0.

Answered By: jfs

In python 3 the __self__ attribute is only set on bound methods. It’s not set to None on plain functions (or unbound methods, which are just plain functions in python 3).

Use something like this:

def is_bound(m):
    return hasattr(m, '__self__')
Answered By: Rob Agar

The chosen answer is valid in almost all cases. However when checking if a method is bound in a decorator using chosen answer, the check will fail. Consider this example decorator and method:

def my_decorator(*decorator_args, **decorator_kwargs):
    def decorate(f):
        print(hasattr(f, '__self__'))
        @wraps(f)
        def wrap(*args, **kwargs):
            return f(*args, **kwargs)
        return wrap
    return decorate

class test_class(object):
    @my_decorator()
    def test_method(self, *some_params):
        pass

The print statement in decorator will print False.
In this case I can’t find any other way but to check function parameters using their argument names and look for one named self. This is also not guarantied to work flawlessly because the first argument of a method is not forced to be named self and can have any other name.

import inspect

def is_bounded(function):
    params = inspect.signature(function).parameters
    return params.get('self', None) is not None
Answered By: Klaus

A solution that works for both Python 2 and 3 is tricky.

Using the package six, one solution could be:

def is_bound_method(f):
    """Whether f is a bound method"""
    try:
        return six.get_method_self(f) is not None
    except AttributeError:
        return False

In Python 2:

  • A regular function won’t have the im_self attribute so six.get_method_self() will raise an AttributeError and this will return False
  • An unbound method will have the im_self attribute set to None so this will return False
  • An bound method will have the im_self attribute set to non-None so this will return True

In Python 3:

  • A regular function won’t have the __self__ attribute so six.get_method_self() will raise an AttributeError and this will return False
  • An unbound method is the same as a regular function so this will return False
  • An bound method will have the __self__ attribute set (to non-None) so this will return True
Answered By: Anakhand
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.