2017-04-19 86 views
5

有没有一种方法可以在函数内知道该函数是被自己调用还是赋值给一个变量=?函数可以知道它是如何被调用的吗?

我愿做这样的事情:

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

,会给那些输出:

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

这是不可能的。 –

+1

我不会尝试这样做。有1个版本返回,然后在呼叫站点打印返回值(如有必要)。一般来说,您应该尝试让函数始终返回相同的类型,或者至少一致地返回可用值或不返回。 – Carcigenicate

+1

在类的情况下,你可以通过分配一个类变量来完成它。 – Thameem

回答

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(): 
+0

如果它不回答问题,这怎么可能被接受?为了得到名字,函数被调用,并且源代码行绝对不足以确定结果是否被分配给名称。 – BlackJack

+0

@BlackJack这是足够的信息,你只需要编写自己的逻辑。电话在那里,名字就在那里。你如何确定名称是否在通话中取决于你。 –

+0

@BlackJack我并不要求这个函数是失败的,这个答案给了元素来产生我在问题中描述的结果。该函数不能用于其他情况的事实与我的问题无关,但值得注意。 – Seb

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 
+0

这是相当有限的。 'a,b = spam(),func()'或'x = spam(func())'是返回值被分配/使用但未被您的检查识别的情况。这个'func()'有一个非常奇怪和令人惊讶的API。 – BlackJack

相关问题