Can a function know how it was called?

Is there a way to find out inside a function if the function was called on its own or assigned to the variable c =?

I would like to do something like this:

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

which will give these outputs:

 func() -> 'not assigned' a = func() a -> 5 
+5
source share
2 answers

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

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

Note the second and final entry: ['func()\n'] . This shows the code that calls your function. Although the function name is displayed elsewhere on the stack, it always shows the actual function name, regardless of how it is called. Therefore, you need to do a little work yourself to determine if the call was made directly or using an assigned variable.

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

To make it clear that this will be more complicated than just if func_name in stack , I covered the function a bit to show a couple of real-life examples of how the function can be called and how it will look, Since the function cannot determine its own name, it is hard-coded 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 

Fingerprints:

 func() return_value = x(var=1) print func() None # This prints from the call, because `func()` doesn't return anything if x(): 
+2
source

Here is an example of the work that I wrote based on the accepted answer. We cannot assign a new function name, but it does what I wanted to do

 import inspect # generator function to get all the strings in an iterable object def descend_strings(obj): if hasattr(obj,'__iter__'): if type(obj)==dict: for key in obj: for result in descend_strings(obj[key]): yield result else: for item in obj: for result in descend_strings(item): yield result if type(obj)==str: yield obj def func(): stack = inspect.stack() joined_flat_stack_str = ''.join(list(descend_strings(stack))) if ('= func()' in joined_flat_stack_str) or ('print func()' in joined_flat_stack_str): return 5 else: print 'not assigned' func() # 'not assigned' a = func() print a # 5 print func() # 5 x = func x() # 'not assigned' a = x() # 'not assigned' print a # None 
0
source

Source: https://habr.com/ru/post/1266921/


All Articles