How to get current function into a variable?

The stack frame tells us what code object we’re in. If we can find a function object that refers to that code object in its __code__ attribute, we have found the function.

Fortunately, we can ask the garbage collector which objects hold a reference to our code object, and sift through those, rather than having to traverse every active object in the Python world. There are typically only a handful of references to a code object.

Now, functions can share code objects, and do in the case where you return a function from a function, i.e. a closure. When there’s more than one function using a given code object, we can’t tell which function it is, so we return None.

import inspect, gc

def giveupthefunc():
    frame = inspect.currentframe(1)
    code  = frame.f_code
    globs = frame.f_globals
    functype = type(lambda: 0)
    funcs = []
    for func in gc.get_referrers(code):
        if type(func) is functype:
            if getattr(func, "__code__", None) is code:
                if getattr(func, "__globals__", None) is globs:
                    funcs.append(func)
                    if len(funcs) > 1:
                        return None
    return funcs[0] if funcs else None

Some test cases:

def foo():
    return giveupthefunc()

zed = lambda: giveupthefunc()

bar, foo = foo, None

print bar()
print zed()

I’m not sure about the performance characteristics of this, but i think it should be fine for your use case.

Leave a Comment