如何在python中另一个类的函数中获取调用者类名?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/17065086/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the caller class name inside a function of another class in python?
提问by Kaushik
My objective is to stimulate a sequence diagram of an application for this I need the information about a caller and callee class names at runtime. I can successfully retrieve the caller function but not able to get a caller class name?
我的目标是激发一个应用程序的序列图,我需要在运行时有关调用者和被调用者类名的信息。我可以成功检索调用者函数但无法获取调用者类名?
#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()
When I printed the stack there was no information about the caller class. So is it possible to retrieve the caller class during runtime ?
当我打印堆栈时,没有关于调用者类的信息。那么是否可以在运行时检索调用者类?
采纳答案by brice
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:
给定文件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.
不确定从对象以外的东西调用时它会如何表现。
回答by mgilson
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.
显然,这会返回对类本身的引用。如果您想要类的名称,可以从__name__属性中获取。
Unfortunately, this won't work for class or static methods ...
不幸的是,这不适用于类或静态方法......
回答by Justin S Barrett
Perhaps this is breaking some Python programming protocol, but if Bad is alwaysgoing to check the class of the caller, why not pass the caller's __class__to it as part of the call?
也许这破坏了一些 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()
Result:
结果:
Hello
dude
Calling class: __main__.A
If this is bad form, and using inspecttruly is the preferred way to get the caller's class, please explain why.  I'm still learning about deeper Python concepts.
如果这是不好的形式,并且使用inspect真正是获取调用者类的首选方式,请解释原因。我仍在学习更深层次的 Python 概念。
回答by Mika72
To store class instance name from the stack to class variable:
要将类实例名称从堆栈存储到类变量:
import inspect
class myClass():
    caller = ""
    def __init__(self):
        s = str(inspect.stack()[1][4]).split()[0][2:]
        self.caller = s
    def getInstanceName(self):
        return self.caller
This
这个
myClassInstance1 = myClass()
print(myClassInstance1.getInstanceName())
will print:
将打印:
myClassInstance1
回答by djeongo
Instead of indexing the return value of inspect.stack(), one could use the method inspect.currentframe(), which avoids the indexing.
可以使用方法inspect.currentframe() 来避免索引,而不是索引inspect.stack() 的返回值。
prev_frame = inspect.currentframe().f_back
the_class = prev_frame.f_locals["self"].__class__
the_method = prev_frame.f_code.co_name
回答by Джон Смит
Python 3.8
蟒蛇 3.8
import inspect
class B:
    def __init__(self):
        if (parent := inspect.stack()[1][0].f_locals.get('self', None)) and isinstance(parent, A):
            parent.print_coin()
class A:
    def __init__(self, coin):
        self.coin: str = coin
        B()
    def print_coin(self):
        print(f'Coin name: {self.coin}')
A('Bitcoin')

