【发布时间】:2010-09-08 08:50:55
【问题描述】:
给定一个方法的引用,有没有办法检查该方法是否绑定到一个对象?你也可以访问它绑定的实例吗?
【问题讨论】:
给定一个方法的引用,有没有办法检查该方法是否绑定到一个对象?你也可以访问它绑定的实例吗?
【问题讨论】:
im_self attribute(仅限 Python 2)
【讨论】:
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 and 3.0:
实例方法对象有新的 对象和函数的属性 包括该方法;新的同义词 对于
im_self是__self__和im_func也可作为__func__使用。老人 Python 仍然支持名称 2.6,但在 3.0 中消失了。
【讨论】:
在 python 3 中,__self__ 属性仅设置在绑定方法上。在普通函数(或未绑定的方法,它们只是 python 3 中的普通函数)上,它没有设置为 None。
使用这样的东西:
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
【讨论】:
f 从来没有真正绑定到test_class,这就是这里的复杂性。甚至decorate 也没有绑定(您可以通过检查 test_class.test_method != decorate 来验证)。绑定方法是从 decorate 创建的,而 that 是附加到 test_class 的内容。您真正要查找的是是否已从特定函数创建了绑定方法。我不确定这是否可能
同时适用于 Python 2 和 3 的解决方案很棘手。
使用包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() 将引发AttributeError,这将返回False
im_self 属性设置为None,因此这将返回False
im_self 属性设置为非None,因此这将返回True
在 Python 3 中:
__self__ 属性,因此six.get_method_self() 将引发AttributeError,这将返回False
False
__self__ 属性(设置为非None),因此这将返回True
【讨论】: