How to get the caller class name inside a function of another class in python?

前端 未结 6 785
花落未央
花落未央 2020-12-02 19:08

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 retrie

相关标签:
6条回答
  • 2020-12-02 19:18

    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.

    0 讨论(0)
  • 2020-12-02 19:19

    Instead of indexing the return value of inspect.stack(), one could use the method inspect.currentframe(), which avoids the indexing.

    prev_frame = inspect.currentframe().f_back
    the_class = prev_frame.f_locals["self"].__class__
    the_method = prev_frame.f_code.co_name
    
    0 讨论(0)
  • 2020-12-02 19:24

    Python 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')
    
    0 讨论(0)
  • 2020-12-02 19:30

    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 ...

    0 讨论(0)
  • 2020-12-02 19:43

    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.

    0 讨论(0)
  • 2020-12-02 19:43

    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
    
    0 讨论(0)
提交回复
热议问题