一个函数可以知道它是如何被调用的吗?

时间:2017-04-19 14:27:57

标签: python

有没有办法在函数中知道函数是单独调用还是赋值给变量=?

我想做这样的事情:

def func():
    if 'assigned with equal':
        return 5
    else:
        print 'not assigned'

会产生这些输出:

func()
-> 'not assigned'
a = func()
a
-> 5

2 个答案:

答案 0 :(得分:2)

是的,有一种方法可以做到这一点,虽然做对了会很棘手。您可以使用inspect模块访问调用堆栈。这允许您查看调用该函数的代码。

堆栈看起来像这样:

[(<frame object at 0x107de1d38>, 'path/to/function/file.py', 6, 'func', ['\tstack = inspect.stack()\n'], 0), (<frame object at 0x107d34050>, 'path/to/calling/file.py', 17, '<module>', ['func()\n'], 0)]

注意倒数第二个条目:['func()\n']。这显示调用您的函数的代码。即使函数的名称显示在堆栈的其他位置,它也始终显示函数的实际名称,无论它如何调用。因此,您必须自己做一些工作,以确定是直接调用还是通过指定的变量进行调用。

这是获取函数名称的唯一方法。 Python does not have a feature从函数本身中检索函数名称。

为了说清楚这将比if func_name in stack更难,我已经充实了这个功能,以展示一些关于如何调用函数的真实世界的例子以及什么看起来像。由于该函数无法确定自己的名称,因此它在函数顶部进行了硬编码。

import inspect


def func(var=None, default=''):
    my_name = 'func'
    stack = inspect.stack()
    func_call = stack[-1][4][0]
    print func_call.rstrip()  # `func_call` contains a trailing newline

    # logic to determine if the name matches
    # ...
    # ...


x = func
func()
return_value = x(var=1)
print func()
if x():
    pass

打印:

func()
return_value = x(var=1)
print func()
None  # This prints from the call, because `func()` doesn't return anything
if x():

答案 1 :(得分:0)

这是我根据接受的答案编写的一个运行示例。我们不能为该函数指定一个新名称,但它会执行我想要做的事情

import inspect

# generator function to get all the strings in an iterable object
def descend_strings(obj):
    if hasattr(obj,'__iter__'):
        if type(obj)==dict:
            for key in obj:
                for result in descend_strings(obj[key]):
                    yield result
        else:
            for item in obj:
                for result in descend_strings(item):
                    yield result
    if type(obj)==str:
        yield obj

def func():
    stack = inspect.stack()

    joined_flat_stack_str = ''.join(list(descend_strings(stack)))

    if ('= func()' in joined_flat_stack_str) or ('print func()' in joined_flat_stack_str):
        return 5
    else:
        print 'not assigned'


func()       # 'not assigned'
a = func()   
print a      # 5
print func() # 5

x = func
x()          # 'not assigned'
a = x()      # 'not assigned'
print a      # None