0

我有两个python函数A()和B(),它们都调用f1(),而f1()调用f2()......在f4()中,我想获取原始函数名称(A或B),有什么聪明的方法吗?我以为我可以为每个函数添加一个参数,但这使我的代码非常难看。这些函数在不同的文件中,有些在新线程中开始,我还阅读了一些关于上下文的文档,但我不确定它是否在这里有效。

def A():
    f1()

def B():
    f1()


def f1():
    f2()

def f2():
    f3()

def f3():
    f4()

def f4():

    if call_from_A:
        print(123)
    else:
        print(456)
4

3 回答 3

0

您的问题归结为“我处于哪种工作流程中?” 解决此类问题的传统方法是使用面向对象的模式。正确使用面向对象的设计通常会消除条件。

将方法放在一个类上。您可以在实例化时传递“它是什么”,也可以根据您的需要使用继承对其进行建模。

使用单个类并在实例化时传递“种类”:

class Workflow:

    def __init__(self, kind):
        self.kind = kind

    def f1(self):
        self.f2()

    def f2(self):
        self.f3()

    def f3(self):
        self.f4()

    def f4(self):
        print(self.kind)

 # now use it

 a = Workflow(123)
 b = Workflow(456)

 a.f1()     # prints 123
 b.f1()     # prints 456

注意没有if涉及。没有必要。这样的事情会错过重点:

def f4(self):
    if self.kind == "A":
        print(123)
    else if self.kind == "B":
        print(456)

早先在实例化对象时进行了区分。此后,每个实例都有自己的行为,这些行为不基于任何东西。

如果这两个工作流具有更复杂的行为(例如f4(),实际上做了一些重要的工作),那么您可能需要继承。定义一个基类,然后将其子类化为您希望能够创建的每种事物。

 class WorkflowBase:

    def f1(self):
        self.f2()

    def f2(self):
        self.f3()

    def f3(self):
        self.f4()

    def f4(self):
        return

class WorkflowA(WorkflowBase):

    def f4(self):
         print(123)

class WorkflowB(WorkflowBase):

    def f4(self):
         print(456)

# using them

a = WorkflowA()
b = WorkflowB()

a.f1()     # prints 123
b.f1()     # prints 456

在这里,行为被融入其中,WorkflowA或者WorkflowB,您拥有一个类或另一个类的实例这一事实激活了不同的结果。

它也不需要您检查调用堆栈,这是一个相当复杂的条件。这样做很有趣,我很了解它的魅力,但它很慢,而且它会让你的代码难以被其他人理解。

于 2021-08-17T03:11:22.813 回答
0

我们可以使用inspectfrom Python来识别这一点。

import inspect


def f4():
    curframe = inspect.currentframe()
    calframe = inspect.getouterframes(curframe, 2)
    call_from_A = calframe[4].function == "A"

    if call_from_A:
        print(123)
    else:
        print(456)

请注意,如果更改了函数的嵌套,则必须适当地修改calframe[4]行中的内容。call_from_A = calframe[4].function == "A"换句话说,[4]被硬编码为“在帧堆栈中返回 4 次”(即 f4 <- f3 <- f2 <- f1 <-source)。

于 2021-08-17T02:52:19.060 回答
0

您可以使用traceback 模块来执行此操作。它将为您提供整个调用堆栈,您可以对其进行解析以获取所需的信息。

例子:

import traceback


def A():
    f1()

def B():
    f1()


def f1():
    f2()

def f2():
    f3()

def f3():
    f4()

def f4():
    tb = traceback.extract_stack()
    call_chain = [f.name for f in tb]
    if 'A' in call_chain:
        print('Called from A')
    elif 'B' in call_chain:
        print('Called from B')
    
        
def main():
    A()
    B()
    
        
if __name__ == '__main__':
    main()
于 2021-08-17T02:51:27.323 回答