Я не верю, что на уровне объекта фрейма есть какой-либо способ найти действительный объект функции python, который был вызван.
Однако, если ваш код основан на общем соглашении: присваивая имя экземпляру метода self
, вы можете сделать следующее:
def get_class_from_frame(fr):
import inspect
args, _, _, value_dict = inspect.getargvalues(fr)
# we check the first parameter for the frame function is
# named 'self'
if len(args) and args[0] == 'self':
# in that case, 'self' will be referenced in value_dict
instance = value_dict.get('self', None)
if instance:
# return its class
return getattr(instance, '__class__', None)
# return None otherwise
return None
Если вы не хотите использовать getargvalues
, вы можете напрямую использовать frame.f_locals
вместо value_dict
и frame.f_code.co_varnames[:frame.f_code.co_argcount]
вместо args
.
Имейте в виду, что это все еще зависит только от соглашения, поэтому оно не переносимо и подвержено ошибкам:
- если функция, не относящаяся к методу, использует
self
в качестве имени первого параметра, то get_class_from_frame
ошибочно вернет класс первого параметра.
- это может вводить в заблуждение при работе с дескрипторами (будет возвращать класс дескриптора, а не фактического экземпляра, к которому осуществляется доступ).
@classmethod
и @staticmethod
не принимают параметр self
и реализованы с помощью дескрипторов.
- и, конечно, намного больше
В зависимости от того, что именно вы хотите сделать, вам может потребоваться некоторое время, чтобы копать глубже и находить обходные пути для всех этих проблем (вы можете проверить, что функция фрейма существует в возвращаемом классе и имеет общий источник, обнаруживая вызовы дескриптора возможно, то же самое для методов класса и т.д ..)