Aliased name of a Function in Python

让人想犯罪 __ 提交于 2020-01-25 03:26:04

问题


I want to find the name of the function as it was called ... i.e. the name of the variable that called the function. Using the basic recipes i.e. with __name__, func_name, or inspecting the basic stack does not work for me. For example

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"

My gut says I can do this, but I can't figure it out. Any python guru's out there?


回答1:


It's probably impossible to do this 100% correctly, but you could give the following a try:

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

This will print:

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

It's pretty ugly and complicated, but might work for what you need. It works by finding all variables used in the line that called this function and comparing them to the current function.




回答2:


The problem here is indirection. You could probably do something complicated like inspect the stack, get the code for the module that called the function, parse the line number from the stack to find the label used to call the function in the local context, and then use that, but that won't necessarily give you what you want anyway. Consider:

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

Should this print func, func_in_func_wrapper, func_label, or func_from_func_wrapper? It might seem like an obvious answer at first, but given that you never really know what sort of indirection is going on inside code you are calling, you really can't know for sure.



来源:https://stackoverflow.com/questions/11547095/aliased-name-of-a-function-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!