44

给定一个方法的引用,有没有办法检查该方法是否绑定到一个对象?您还可以访问它绑定到的实例吗?

4

5 回答 5

45
def isbound(method):
    return method.im_self is not None

def instance(bounded_method):
    return bounded_method.im_self

用户定义的方法:

当通过从类中检索用户定义的函数对象来创建用户定义的方法对象时,它的 im_self属性是None并且方法对象被称为未绑定的。当通过其实例之一从类中检索用户定义的函数对象来创建一个时,它的 im_self属性是实例,并且方法对象被称为绑定。在任何一种情况下,新方法的 im_class属性都是从中进行检索的类,其im_func属性是原始函数对象。

在 Python 2.6 和 3.0中:

实例方法对象具有包含该方法的对象和函数的新属性;的新同义词im_selfis__self__im_func 也可用作__func__. Python 2.6 仍支持旧名称,但在 3.0 中已不复存在。

于 2008-09-10T02:19:09.050 回答
25

在 python 3 中,该__self__属性在绑定方法上设置。它没有设置为None普通函数(或未绑定的方法,它们只是 python 3 中的普通函数)。

使用这样的东西:

def is_bound(m):
    return hasattr(m, '__self__')
于 2013-09-23T09:03:57.013 回答
11

选择的答案几乎在所有情况下都有效。但是,当使用选择的答案检查方法是否绑定在装饰器中时,检查将失败。考虑这个示例装饰器和方法:

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

装饰器中的print语句将打印False。在这种情况下,我找不到任何其他方法,只能使用参数名称检查函数参数并查找名为self. 这也不能保证完美地工作,因为方法的第一个参数不是强制命名的self,可以有任何其他名称。

import inspect

def is_bounded(function):
    params = inspect.signature(function).parameters
    return params.get('self', None) is not None
于 2018-04-28T08:39:51.880 回答
4

im_self属性(仅限 Python 2)

于 2008-09-10T00:42:13.167 回答
0

适用于 Python 2 和 3 的解决方案很棘手。

使用 package six,一种解决方案可能是:

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

在 Python 2 中:

  • 常规函数没有该im_self属性,因此six.get_method_self()会引发 anAttributeError并且这将返回False
  • 未绑定的方法将im_self属性设置为,None因此这将返回False
  • 绑定方法将im_self属性设置为 non-None所以这将返回True

在 Python 3 中:

  • 常规函数没有该__self__属性,因此six.get_method_self()会引发 anAttributeError并且这将返回False
  • 未绑定的方法与常规函数相同,因此这将返回False
  • 绑定方法将__self__设置属性(设置为 non- None),因此这将返回True
于 2020-12-13T14:26:54.573 回答