2012-07-18 791 views
1

我想查找調用該函數的名稱......即調用該函數的變量的名稱。使用基本配方,即__name__,func_name,或檢查基本堆棧不適用於我。例如Python中函數的別名

def somefunc(): 
    print "My name is: %s" % inspect.stack()[1][3] 

a = somefunc 
a() 
# would output: out: "My name is: somefunc" 
# whereas I want it to output: "My name is: a" 

我的直覺說我可以做到這一點,但我無法弄清楚。任何蟒蛇大師在外面?

+2

我懷疑這是可能的。你想要這樣做的任何特定原因? – mgilson 2012-07-18 17:34:46

+8

通常當人們問如何做這樣的事情時,他們正在做一件非常糟糕的事情。你能澄清這將起什麼作用嗎? – cdhowie 2012-07-18 17:35:37

+0

您可以更改零件的__name__,但我不明白爲什麼要這樣做。另外,看看裝飾文檔。 – sean 2012-07-18 17:35:40

回答

1

它可能無法正確地做這個100%,但你可以給以下嘗試:

import inspect 
import parser 

# this flatten function is by mike c fletcher 
def flatten(l, ltypes=(list, tuple)): 
    ltype = type(l) 
    l = list(l) 
    i = 0 
    while i < len(l): 
     while isinstance(l[i], ltypes): 
      if not l[i]: 
       l.pop(i) 
       i -= 1 
       break 
      else: 
       l[i:i + 1] = l[i] 
     i += 1 
    return ltype(l) 

# function we're interested in 
def a(): 
    current_func = eval(inspect.stack()[0][3]) 
    last_frame = inspect.stack()[1] 
    calling_code = last_frame[4][0] 
    syntax_tree = parser.expr(calling_code) 
    syntax_tree_tuple = parser.st2tuple(syntax_tree) 
    flat_syntax_tree_tuple = flatten(syntax_tree_tuple) 
    list_of_strings = filter(lambda s: type(s)==str,flat_syntax_tree_tuple) 
    list_of_valid_strings = [] 
    for string in list_of_strings: 
     try: 
      st = parser.expr(string) 
      list_of_valid_strings.append(string) 
     except: 
      pass 
    list_of_candidates = filter(lambda s: eval(s)==current_func, list_of_valid_strings) 
    print list_of_candidates 

# other function 
def c(): 
    pass 

a() 
b=a 
a(),b(),c() 
a(),c() 
c(),b() 

這將打印:

['a'] 
['a', 'b'] 
['a', 'b'] 
['a'] 
['b'] 

這實在是太醜陋和複雜的,但可能工作爲你所需要的。它通過查找調用該函數的行中使用的所有變量並將它們與當前函數進行比較來工作。

+0

我喜歡這個,這是我想要寫的東西的本質......就像你說的那樣很複雜。而且我不能真正分配返回值,因此我可以使用它的a()函數,因爲解析器給出了語法錯誤。 – Pykler 2012-07-19 17:53:48

+0

要使用返回值,我創建了list_of_candidates全局。雖然更簡單的解決方案將是下一個挑戰,但您的答案適用於我想要做的事!謝謝! – Pykler 2012-07-19 18:12:45

1

這裏的問題是間接的。你可能會做一些複雜的事情,例如檢查堆棧,獲取調用該函數的模塊的代碼,從堆棧中解析行號以查找用於在本地上下文中調用該函數的標籤,然後使用該標籤無論如何不一定會給你想要的東西。試想一下:

def func(x): 
    print get_label_function_called_with() 

def func_wrapper(func_in_func_wrapper): 
    return func_in_func_wrapper 

func_label = func 
func_from_func_wrapper = func_wrapper(func_label) 
func_from_func_wrapper() 

若本打印funcfunc_in_func_wrapperfunc_label,或func_from_func_wrapper?起初這看起來似乎是一個明顯的答案,但鑑於你從不真正瞭解你所調用的代碼內部發生了什麼樣的間接性,所以你確實無法確定。

+0

這是一個複雜的情況,在我的情況下,我不關心包裝,但其他人可能是。 – Pykler 2012-07-19 17:42:51

+0

關鍵是這就是爲什麼沒有簡單或甚至真的可行的方法來做到這一點。 – 2012-07-19 18:06:03

+0

可能不夠快/可行,但我的問題是關於是否可能......我確信有一種方法比python中選定的答案更強大,因爲python確實是動態的。 – Pykler 2012-07-19 18:50:43