Как получить имя класса вызывающего абонента внутри функции другого класса в python?
Моя цель - стимулировать диаграмму последовательности приложения для этого. Мне нужна информация о именах вызывающих и вызываемых классов во время выполнения. Я могу успешно получить функцию вызывающего абонента, но не смог получить имя класса вызывающего абонента?
#Scenario caller.py:
import inspect
class A:
def Apple(self):
print "Hello"
b=B()
b.Bad()
class B:
def Bad(self):
print"dude"
print inspect.stack()
a=A()
a.Apple()
Когда я печатал стек, не было информации о классе вызывающего. Так можно ли получить класс вызывающего абонента во время выполнения?
Ответы
Ответ 1
Ну, после некоторого копания в подсказке, вот что я получаю:
stack = inspect.stack()
the_class = stack[1][0].f_locals["self"].__class__
the_method = stack[1][0].f_code.co_name
print("I was called by {}.{}()".format(str(calling_class), calling_code_name))
# => I was called by A.a()
При вызове:
➤ python test.py
A.a()
B.b()
I was called by __main__.A.a()
задан файл test.py
:
import inspect
class A:
def a(self):
print("A.a()")
B().b()
class B:
def b(self):
print("B.b()")
stack = inspect.stack()
the_class = stack[1][0].f_locals["self"].__class__
the_method = stack[1][0].f_code.co_name
print(" I was called by {}.{}()".format(str(the_class), the_method))
A().a()
Не уверен, как он будет себя вести при вызове от чего-то другого, кроме объекта.
Ответ 2
Использование ответа от Python: как получить информацию о классе из объекта 'frame'?
Я получаю что-то вроде этого...
import inspect
def get_class_from_frame(fr):
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
class A(object):
def Apple(self):
print "Hello"
b=B()
b.Bad()
class B(object):
def Bad(self):
print"dude"
frame = inspect.stack()[1][0]
print get_class_from_frame(frame)
a=A()
a.Apple()
который дает мне следующий результат:
Hello
dude
<class '__main__.A'>
ясно, что это возвращает ссылку на сам класс. Если вы хотите имя класса, вы можете получить это из атрибута __name__
.
К сожалению, это не будет работать для классов или статических методов...
Ответ 3
Возможно, это нарушает некоторые протоколы программирования Python, но если Bad всегда проверяет класс вызывающего, почему бы не передать вызывающему абоненту __class__
ему как часть вызова?
class A:
def Apple(self):
print "Hello"
b=B()
b.Bad(self.__class__)
class B:
def Bad(self, cls):
print "dude"
print "Calling class:", cls
a=A()
a.Apple()
Результат:
Hello
dude
Calling class: __main__.A
Если это плохая форма, и использование inspect
действительно является предпочтительным способом получить класс вызывающего абонента, объясните, почему. Я все еще изучаю более глубокие концепции Python.