Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a function know how it has been called?

Tags:

python

Is there a way to know within a function if the function has been called by itself or assigned to a variable with = ?

I would like to do something like this:

def func():
    if 'assigned with equal':
        return 5
    else:
        print 'not assigned'

that would give those outputs:

func()
-> 'not assigned'
a = func()
a
-> 5
like image 512
Seb Avatar asked Oct 29 '22 09:10

Seb


1 Answers

Yes, there is a way to do this, though getting it right will be tricky. You can use the inspect module to access the call stack. This allows you to see what the code looks like that called the function.

The stack looks something like this:

[(<frame object at 0x107de1d38>, 'path/to/function/file.py', 6, 'func', ['\tstack = inspect.stack()\n'], 0), (<frame object at 0x107d34050>, 'path/to/calling/file.py', 17, '<module>', ['func()\n'], 0)]

Notice the second to last entry: ['func()\n']. This is showing the code that calls your function. Even though the name of the function shows up elsewhere in the stack, it always shows the actual name of the function no matter how it is called. So you have to do a little work on your own to determine whether or not the call was made directly or through an assigned variable.

This is the only way to get the function name. Python does not have a feature to retrieve the function name from within the function itself.

To make it clear that this will be more difficult than just if func_name in stack, I've fleshed out the function a little bit to show a couple of real world examples of how a function might be called and what it would look like. Because the function can't determine its own name, it is hardcoded at the top of the function.

import inspect


def func(var=None, default=''):
    my_name = 'func'
    stack = inspect.stack()
    func_call = stack[-1][4][0]
    print func_call.rstrip()  # `func_call` contains a trailing newline

    # logic to determine if the name matches
    # ...
    # ...


x = func
func()
return_value = x(var=1)
print func()
if x():
    pass

This prints:

func()
return_value = x(var=1)
print func()
None  # This prints from the call, because `func()` doesn't return anything
if x():
like image 74
Darrick Herwehe Avatar answered Nov 15 '22 05:11

Darrick Herwehe