2017-04-19 83 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

相關問題