函数可以知道它是如何被调用的吗?
有没有一种方法可以在函数内知道该函数是被自己调用还是赋值给一个变量=?函数可以知道它是如何被调用的吗?
我愿做这样的事情:
def func():
if 'assigned with equal':
return 5
else:
print 'not assigned'
,会给那些输出:
func()
-> 'not assigned'
a = func()
a
-> 5
是的,有一种方法可以做到这一点,虽然得到它的权利将是非常棘手。您可以使用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():
这里是一个正在运行的例子,我根据公认的答案写道。我们不能为该功能指定一个新的名称,但它做我想做的事
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
这是相当有限的。 'a,b = spam(),func()'或'x = spam(func())'是返回值被分配/使用但未被您的检查识别的情况。这个'func()'有一个非常奇怪和令人惊讶的API。 – BlackJack
这是不可能的。 –
我不会尝试这样做。有1个版本返回,然后在呼叫站点打印返回值(如有必要)。一般来说,您应该尝试让函数始终返回相同的类型,或者至少一致地返回可用值或不返回。 – Carcigenicate
在类的情况下,你可以通过分配一个类变量来完成它。 – Thameem