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

Python 是否可以确定一个函数是在另一个函数体中调用的,还是作为函数的参数调用的?,python,code-analysis,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 def funcA(): func() def funcB(arg1): pass def funcC(**kwargs): pass

假设我们有一个Python函数:

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

def funcC(**kwargs):
    pass

funcB(func())
funcC(kwarg1=func())
func()可以在另一个函数体中调用:

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

def funcC(**kwargs):
    pass

funcB(func())
funcC(kwarg1=func())
func()也可以作为函数的参数调用:

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

def funcC(**kwargs):
    pass

funcB(func())
funcC(kwarg1=func())
在func()的主体中有没有办法区分这两种情况

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

编辑2。代码修补对我来说也足够了。例如,当在另一个函数体中调用func时,所有情况都会替换为

call_function_on_the_right()>>func()

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

可能吗?可能是

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

您可以找出从中调用的那一行,并读取源文件以查看该行如何调用函数。 然而,这有两个问题


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

    现在,我不是100%肯定它会起作用,但我不明白为什么它不会起作用。我能看到的唯一一件可能“出错”的事情是,如果跟踪回报值被证明太难。但是,因为您只需要在一行代码的持续时间内跟踪它,就我所见,实际上不应该有任何“不可能”处理的结构


    我并没有说这很容易,只是说这是可能的

    你为什么要知道这些?你的用例是什么?听起来你实际上有两个不同的函数,你把它们塞进了一个。第二种形式只是一个表达式,它的输出用作
    funcB()
    的参数。您还可以使用
    foo=func()
    然后使用
    funcB(foo)
    ,这样就没有什么区别了。或者
    foo=func
    (注意,没有调用,只是对同一函数的引用),然后
    funcB(foo())
    ,调用同一个函数对象。没有简单的方法-
    func
    不需要知道或关心它
    返回的值将在哪里工作。我同意@JoshCaswell,但我会说它更强-糟糕的设计。你可以用python内省做很多事情,但我认为这不应该是其中之一。“源文件可能已经被修改并提供了错误的信息。”请你解释一下或提供一个例子。感谢你的消息,我有了一个想法。在func()之前,我可以数出许多圆括号。如果数字为偶数,则在函数体中调用func()。如果数字是奇数。然后将func()作为函数的参数调用。你认为它会起作用吗?@vvoovv例如,如果有人使用你的“库”,并且有他自己的“零件库”和两个使用它的独立程序,他启动第一个程序,然后添加第二个程序需要的新“零件”。现在,第一个运行的程序正在查看错误的源代码。任何时候当你修改源代码的时候,任何使用它的程序都在运行,它将被完全破坏。(如果某人(例如,仅分发.pyc文件)也可以在许多物理行上断开逻辑行,这将断开括号计数解决方案。(甚至您的示例文件也会这样做)