How to get the caller class name inside a function of another class in python?
Using the answer from Python: How to retrieve class information from a 'frame' object?
I get something like this...
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()
which gives me the following output:
Hello
dude
<class '__main__.A'>
clearly this returns a reference to the class itself. If you want the name of the class, you can get that from the __name__
attribute.
Unfortunately, this won't work for class or static methods ...
Perhaps this is breaking some Python programming protocol, but if Bad is always going to check the class of the caller, why not pass the caller's __class__
to it as part of the call?
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()
Result:
Hello
dude
Calling class: __main__.A
If this is bad form, and using inspect
truly is the preferred way to get the caller's class, please explain why. I'm still learning about deeper Python concepts.
Well, after some digging at the prompt, here's what I get:
stack = inspect.stack()
the_class = stack[1][0].f_locals["self"].__class__.__name__
the_method = stack[1][0].f_code.co_name
print("I was called by {}.{}()".format(the_class, the_method))
# => I was called by A.a()
When invoked:
➤ python test.py
A.a()
B.b()
I was called by A.a()
given the file 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__.__name__
the_method = stack[1][0].f_code.co_name
print(" I was called by {}.{}()".format(the_class, the_method))
A().a()
Not sure how it will behave when called from something other than an object.