如何在python中找到调用函数类?

bol*_*eld 5 python

我试图在python中确定一个调用函数的拥有类.例如,我有两个类,ClassA和ClassB.我想知道classb_instance.call_class_a_method()是class_a.class_a_method()的调用者,这样:

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

输出将是:

'ClassB is not calling.'
'ClassB is calling.'
Run Code Online (Sandbox Code Playgroud)

似乎检查应该能够做到这一点,但我不知道如何.

Dan*_*uev 7

好吧,如果你想遍历调用堆栈并找到哪个类(如果有的话)调用它,那么它很简单:

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

如果要检查调用者是否为ClassB类型,则应使用isinstance(caller, ClassB)而不是比较__class__.然而,这通常是非pythonic,因为python是鸭子类型.

正如其他人所说,很可能您的应用需要重新设计以避免使用inspect.stack.它的CPython实现功能,并不保证在其他Python实现中出现.此外,它只是错误的事情.

  • 我最近发现inspect.stack可能非常慢 - 应该使用inspect.currentframe(n)而不是inspect.stack()[n] [0] - (当然,_if_一个人正在这样做 - 以前在生产中对它的考虑大多是有效的 - 除了它在cPython中足够一致) (3认同)

Ale*_*lli 4

函数不“拥有”类——一个或多个类可以(但不一定)引用给定的函数对象,例如:

def f(self): return g()

class One(object): bah = f

class Two(object): blup = f

def g(): ...
Run Code Online (Sandbox Code Playgroud)

One.bahTwo.blup都设置为对同一函数对象的引用f(并且在类或其实例上访问时变成未绑定或绑定方法对象,但这不会在堆栈中留下任何痕迹)。所以,堆栈上

One().f()
Run Code Online (Sandbox Code Playgroud)

Two().f()
Run Code Online (Sandbox Code Playgroud)

从这g()两种情况下调用的 that 可以看出,确实很难区分——就像由例如,

f('blah bloh blup')
Run Code Online (Sandbox Code Playgroud)

根本不涉及“类”(尽管用作参数的字符串类型是;-)。fself

我建议不要依赖内省——尤其是狂野和毛茸茸的类型,有很多启发式,需要在这里获取任何半有用的信息——对于任何生产代码要求:重新架构以避免这种需要。

出于纯粹的调试目的,在这种情况下,您可以遍历堆栈,直到找到第一个参数名为的调用函数,self并内省绑定到该参数名称的值的类型 - 但正如我提到的,这完全是启发式的,因为没有任何强制self当且仅当它们的函数是某个类中的方法时,调用者才能命名它们的第一个参数。

在我刚刚给出的三个代码示例中,这种启发式内省将产生类型对象OneTwostr,如您所见,除了调试之外,绝对没有其他好处;-)。

如果您通过这次尝试的内省更好地明确了您想要实现的目标,我们当然可以更好地帮助您。

  • 哇,我还有很多东西要学。我想要实现的目标是让一个对象根据另一个对象是否调用它来将自己视为另一个对象的子对象。阅读这里的评论,我意识到这种方法是多么愚蠢,因为孩子不应该关心它是否属于任何其他对象。使用父级作为调解者可以从表中消除整个内省问题,并无限地简化问题。*叹* (3认同)