给定一个方法的引用,有没有办法检查该方法是否绑定到一个对象?您还可以访问它绑定到的实例吗?
5 回答
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_self
is__self__
和im_func
也可用作__func__
. Python 2.6 仍支持旧名称,但在 3.0 中已不复存在。
在 python 3 中,该__self__
属性仅在绑定方法上设置。它没有设置为None
普通函数(或未绑定的方法,它们只是 python 3 中的普通函数)。
使用这样的东西:
def is_bound(m):
return hasattr(m, '__self__')
选择的答案几乎在所有情况下都有效。但是,当使用选择的答案检查方法是否绑定在装饰器中时,检查将失败。考虑这个示例装饰器和方法:
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
im_self属性(仅限 Python 2)
适用于 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