Search code examples
pythonintrospection

Aliased name of a Function in Python


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?


Solution

  • 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.