开发者

How can one find Class of calling function in python?

I am trying to determine the owning class of a calling function in python. For example, I have two classes, ClassA and ClassB. I want to know when classb_instance.call_class_a_method() is the caller of class_a.class_a_method() such that:

class ClassA(object):
    def class_a_method(self):
        # Some unknown process would occur here to
        # define caller. 
        if caller.__class__ == ClassB:
            print 'ClassB is calling.'
        else:
            print 'ClassB is not calling.'

class ClassB(object):
    def __init__(开发者_C百科self):
        self.class_a_instance = ClassA()
    def call_class_a_method(self):
        self.class_a_instance.class_a_method()

classa_instance = ClassA()
classa_instance.class_a_method()
classb_instance = ClassB()
classb_instance.call_class_a_method()

the output would be:

'ClassB is not calling.'
'ClassB is calling.'

It seems as though inspect should be able to do this, but I cant puzzle out how.


Well, if you want to traverse call stack and find which class (if any) did call it, its trivial:

def class_a_method(self):
    stack = inspect.stack()
    frame = stack[1][0]
    caller = frame.f_locals.get('self', None)

If you want to check whether caller is of type ClassB, you should use isinstance(caller, ClassB) rather than comparsion on __class__. However this is generally un-pythonic, since python is duck-typed.

As others stated, most likely your app needs redesign to avoid using inspect.stack. Its CPython implementation feature, and is not guaranteed to be present in other Python implementations. Besides, its just Wrong Thing To Do.


A function does not "have" a class -- one or more classes may (but need not) refer to a given function object, e.g.:

def f(self): return g()

class One(object): bah = f

class Two(object): blup = f

def g(): ...

One.bah and Two.blup are both set as references to the same function object f (and turn into unbound or bound method objects when accessed on the classes or their instances, but that leaves no trace in the stack). So, the stack upon

One().f()

vs

Two().f()

as seen from the g() that's called in either case, is pretty hard indeed to distinguish -- as would be that resulting from, e.g.,

f('blah bloh blup')

with no "classes" involved at all (though the type of the string being used as f's self argument would be;-).

I recommend not relying on introspection -- especially the wild and wooly kind, with lots of heuristics, that would be needed to get any semi-useful info here -- for any production code requirements: rearchitect to avoid that need.

For purely debugging purposes, in this case, you could walk the stack until you find a calling function with a first argument named self and introspect the type of the value bound to that argument name -- but as I mentioned that's entirely heuristical, since nothing forces your callers to name their first argument self if and only if their functions are meant to be methods in some class.

Such heuristic introspection would produce type objects One, Two, and str, in the three examples of code I just gave -- as you see, definitely not good for much else than debugging;-).

If you clarify better exactly what you're trying to accomplish through this attempted introspection, we might of course be able to help you better.


class ClassA( object ):
    def class_a_method( self ):
        if any( "call_class_a_method" in tup for tup in inspect.stack( ) ):
            print( 'ClassB is calling.' )
        else:
            print( 'ClassB is not calling.' )
# ClassB is not calling.
# ClassB is calling.

Why do you actually need this? It's a nasty hack because it's not something you should have to do.


Usually the caller knows and should use the proper parameters, not to do magic in called class.

Do you need maybe factory class/function which record the Class or to write decorator for that?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜