2012-07-18 2 views
1

함수의 이름, 즉 함수를 호출 한 변수의 이름을 찾고 싶습니다. 기본 요리법 (예 : __name__, func_name)을 사용하거나 기본 스택을 검사하지 않아도됩니다. 예를 들어파이썬에서 함수의 별칭 이름

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

+8

보통 사람들이 이런 식으로 행동하는 법을 물어 보면 정말 무서운 일을하고 있습니다. 이것이 어떤 목적을 위해 사용될 것인지 명확히 할 수 있습니까? – cdhowie

+0

파트의 __name__을 변경할 수는 있지만이를 수행하려는 이유를 이해할 수 없습니다. 또한 데코레이터 문서를 살펴보십시오. – sean

답변

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

+0

반환 값을 사용하려면 list_of_candidates를 전역으로 설정했습니다. 더 간단한 해결책이 다음 과제 일지라도, 당신의 답은 내가하고 싶은 것을 위해 일합니다! 감사! – Pykler

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() 

점검이 인쇄 func, func_in_func_wrapper, func_label, 또는 func_from_func_wrapper? 처음에는 분명한 대답처럼 보일지 모르지만, 호출중인 코드에서 어떤 종류의 간접 지정이 진행되고 있는지 모를 경우, 실제로 알 수는 없습니다.

+0

이것은 복잡한 상황이다. 내 경우에는 래퍼와 관련이 없지만 다른 것들은있을 수있다. – Pykler

+0

요점은 이것을하기위한 쉽지 않거나 실제로 가능한 방법이없는 이유입니다. –

+0

빠르고/실현 가능하지 않을 수도 있지만 내 질문에 관한 가능한 경우 ... 그리고 나는 파이썬에서 선택한 답변보다 훨씬 강력한 방법입니다, 파이썬 진정한 동적이기 때문에 확신합니다. – Pykler