是否可以确定函数是在另一个函数体中调用还是作为函数的参数?

时间:2014-10-11 15:20:45

标签: python code-analysis

假设我们有一个Python函数:

def func():
    # if called in the body of another function, do something
    # if called as argument to a function, do something different
    pass

func()可以在另一个函数的主体中调用:

def funcA():
    func()

func()也可以作为函数的参数调用:

def funcB(arg1):
    pass

def funcC(**kwargs):
    pass

funcB(func())
funcC(kwarg1=func())

有没有办法在func()体中区分这两种情况?

EDIT。这是我的用例。我想使用Python作为基于规则的3D模型生成的语言。每个规则都是一个小的Python函数。每个后续规则都会优化模型并添加其他详细信息。 Here是一个示例规则集。 Here是一个描述规则集如何工作的教程。我的规则语言模仿了一种称为CGA形状语法的规则语言。如果可以解决此StackExchange问​​题,我的规则语言可以大大简化。

EDIT2。代码修补对我来说也足够了。例如,在另一个函数的主体中调用func的所有情况都将替换为类似

的内容
call_function_on_the_right()>>func()

1 个答案:

答案 0 :(得分:1)

其他人已经指出这可能不是一个好主意。您可以通过要求使用例如来实现相同的目标。作为参数时,funct()位于toplevel和funca(),并且两者都可以使用关键字参数调用相同的func(),例如,指定您是在顶级还是在参数中。但我不是在这里争论这是不是一个好主意,我来这里是为了回答这个问题。

有可能吗?可能是。

那你怎么做?嗯,首先要知道的是,您可以使用inspect.stack()来获取有关您调用的上下文的信息。

您可以找出您调用的行并读取源文件以查看该行上如何调用该函数。 但是,这有两个问题。

  1. 源文件可能已被修改并提供错误信息。
  2. 如果你func(func())怎么办?它在同一条线路上以两种方式呼叫!
  3. 要获得准确的信息,您应该查看堆栈中的框架对象。它们有一个包含字节码的f_code成员和一个包含最后一条指令位置的f_lasti成员。使用那些你应该能够找出当前正在调用的行上的哪个函数以及返回值的去向。但是,您必须解析帧的整个字节码(请查看dis模块),并跟踪解释器使用的内部堆栈以查看返回值的位置。

    现在,我并非100%确定它会起作用,但我不明白它为什么不会这样做。我唯一能看到的可能会出现问题"如果跟踪返回值证明太难了。但是因为你只需要在一行代码的持续时间内跟踪它,所以真的不应该是任何不可能的结构#34;据我所知,处理。

    我没有说这很容易,只有这样才有可能。 :)