如何在python中的另一个类的函数内获取调用者类名?

Kau*_*hik 24 python stack runtime sequence-diagram

我的目标是为此激发应用程序的序列图我需要在运行时有关调用者和被调用者类名的信息.我可以成功检索调用函数但无法获取调用者类名称?

#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()
Run Code Online (Sandbox Code Playgroud)

当我打印堆栈时,没有关于调用者类的信息.那么可以在运行时检索调用者类吗?

bri*_*ice 34

好吧,经过一些挖掘提示,这是我得到的:

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()
Run Code Online (Sandbox Code Playgroud)

调用时:

? python test.py
A.a()
B.b()
  I was called by __main__.A.a()
Run Code Online (Sandbox Code Playgroud)

给出文件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()
Run Code Online (Sandbox Code Playgroud)

不确定从对象以外的其他东西调用时它的行为方式.

  • 请注意,这不适用于静态或类方法,因为"self"则不会被定义,或者它不会是类的实例(最有可能) (3认同)
  • 该方法的工作是通过子类中的“ super”调用的。或至少不会是您期望的,因为`type(self)`将是子类的类型,而不是实际拥有该方法的类的类型。 (2认同)
  • 获取调用者类的更准确方法是 stack[1][0].f_locals["__class\_\_"]。返回调用类,而不是第一个参数的类。 (2认同)
  • 这对我来说非常有用。我只是想表达诚挚的谢意。 (2认同)

mgi*_*son 6

使用Python的答案:如何从“框架”对象中检索类信息?

我得到这样的东西...

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()
Run Code Online (Sandbox Code Playgroud)

这给了我以下输出:

Hello
dude
<class '__main__.A'>
Run Code Online (Sandbox Code Playgroud)

显然,这会返回对类本身的引用。如果您想要类的名称,可以从__name__属性中获取。

不幸的是,这不适用于类或静态方法......


小智 6

可以使用方法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
Run Code Online (Sandbox Code Playgroud)


Jus*_*ett 5

也许这违反了一些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()
Run Code Online (Sandbox Code Playgroud)

结果:

Hello
dude
Calling class: __main__.A
Run Code Online (Sandbox Code Playgroud)

如果这是不好的形式,并且使用inspecttrue 是获取调用者类的首选方法,请解释原因。我仍在学习更深入的 Python 概念。