代码之家  ›  专栏  ›  技术社区  ›  CIsForCookies

我能知道一个函数是直接调用的还是通过一个指定的变量调用的?

  •  -1
  • CIsForCookies  · 技术社区  · 6 年前

    假设我有一个函数 def f(): print 0 我想创建另一个函数 g 然而 G 的实现与 f ,所以我只分配 f 对它:

    def f():
        print 0
    g = f
    

    你可能会问,如果它们相同,为什么要使用2个函数,这是因为逻辑上,它们代表2个不同的东西

    现在,我能知道是谁打来的吗?我想调试 f() 只有当它通过 G . 这两个呼叫之间的流程不同吗?

    dup的建议与我的问题无关。我知道函数的名称,因为只有一个函数存在。我只希望更进一步,了解是否触发了一个与函数名具有相同值的变量…

    4 回复  |  直到 6 年前
        1
  •  2
  •   iBug    6 年前

    不,至少不能这样做,因为Python不跟踪“查看对象的引用”。我 强烈地 建议你做 g 另一个函数 f 对于一个不那么痛苦的调试体验。

    但是,如果您的代码遵循一些模式,那么您可能会看到 inspect.stack() :

    import inspect
    
    def f():
        stack = inspect.stack()
        print(stack[1].code_context[0].strip())
    
    g = f
    f()
    g()
    

    幸运的是,你会

    f()
    g()
    

    如果你有一些regex技巧,你可以用一个来提取函数名:

    import re
    func_name_re = re.compile(r"\b(\w+)\s*\()")
    
    line = "f()"
    print(func_name_re.search(line).group(1))
    

    但是,如果调用代码 轻微地 更复杂:

    some = f(g())
    some[f()] = g()
    some = f("aaa g() sss")  # string content looks like function call
    some = re.compile(r"^f(?!$)", flags=g())  # same as above
    

    在上面所有的例子中,您很难确定它是否是 f G .

        2
  •  1
  •   user2263572    6 年前

    这行不通。

    输入:

    def f():
        pass
    
    g = f
    
    print(f.__name__)
    print(g.__name__)
    
    print(id(f))
    print(id(g))
    

    输出:

    f
    f
    4350036880
    4350036880
    

    我唯一能想到的解决方法是围绕调用eval并以这种方式处理的函数创建某种类型的包装器(但很可能对您想要做的事情没有意义)。然后可以用func ou name参数调用包装器。

    func_name = 'f'
    
    if func_name =='f':
        ## you know f was called
        eval('f()')
    
        3
  •  0
  •   Klaus D.    6 年前

    如果没有额外的助手或代码分析,就无法做到这一点。

    即使堆栈也不知道被调用的名称:

    >>> def a(): traceback.print_stack()
    ... 
    >>> b = a
    >>> a()
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in a
    >>> b()
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in a
    >>> 
    
        4
  •  0
  •   bruno desthuilliers    6 年前

    我可以推荐最简单的解决方案吗?

    def f():
        print 0
    
    
    def g():
       return f()
    

    现在你清楚地知道什么时候 f 被称为通过 g -您只需要检查调用堆栈。