Имея ссылку на метод, есть ли способ проверить, привязан ли метод к объекту или нет? Можете ли вы также получить доступ к экземпляру, к которому он привязан?






Атрибут im_self (только Python 2)
def isbound(method):
return method.im_self is not None
def instance(bounded_method):
return bounded_method.im_self
Определяемые пользователем методы:
When a user-defined method object is created by retrieving a user-defined function object from a class, its
im_selfattribute isNoneand 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, itsim_selfattribute is the instance, and the method object is said to be bound. In either case, the new method'sim_classattribute is the class from which the retrieval takes place, and itsim_funcattribute is the original function object.
В Python 2.6 и 3.0:
Instance method objects have new attributes for the object and function comprising the method; the new synonym for
im_selfis__self__, andim_funcis also available as__func__. The old names are still supported in Python 2.6, but are gone in 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
Ну, f на самом деле никогда не привязан к test_class, что здесь усложняется. Даже decorate не привязан (вы можете проверить, проверив test_class.test_method! = Decorate). Связанный метод создается из decorate, а который - это то, что присоединено к test_class. На самом деле вы пытаетесь выяснить, был ли связанный метод создан из определенной функции. Я не уверен, возможно ли это
Решение, которое работает как для Python 2, так и для Python 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
Ссылка не работает.