Question Details

No question body available.

Tags

python signature python-internals

Answers (3)

January 15, 2026 Score: 2 Rep: 229,076 Quality: Medium Completeness: 80%

Getting the called function name

I've tried a few different documented options to get the name of the current function from within a function, but, none of these will get the called function name

Right. There is no clean way to do this. The closest we can get is to inspect the calling code context:

import inspect

def common(): whocalled = inspect.stack()[1].codecontext return who_called

specific1 = common specific2 = common

print(specific1()) print(specific2())

This prints:

['print(specific1())\n']
['print(specific2())\n']

Hard coding the name

Is it better to add an argument that specifies the hardcoded function name? The following code gives the desired output - is there a better way?

This approach is completely reliable. However, there is a nicer way to attach the name using functools.partial:

from functools import partial

def commonFuncCore(a=None,b=None,c=3,funcName='COMMON'): print(f'funcName:{funcName} a:{a} b:{b} c:{c}')

f1 = partial(commonFuncCore, funcName='f1') f2 = partial(commonFuncCore, funcName='f2')
January 15, 2026 Score: 1 Rep: 20,141 Quality: Medium Completeness: 100%

This sounds like an XY Problem, and the most Pythonic thing to do here is almost-certainly what's most clear to others!

You're probably best served by another solution like

  • creating a function with an additional argument to choose which logic path it follows (similar to what you propose)
  • creating two normal functions and using them normally
  • creating a class which keeps all or most of the arguments as properties, and which then both functions are modified to expect an instance of as an argument
  • creating a class and making both functions methods of the class (easily shares logic via methods)

That said, if you do choose to have two complete functions, probably does make sense to add a unit test ensuring their arguments are ordered exactly the same to avoid later confusion!

Finally, and while it's a bit of a hack, you can also do something like locals() to unpack all the local names as arguments to a function, avoiding naming them all during the call, but I would only do this for special cases where more terse or dynamic code really is clear and helpful

January 15, 2026 Score: 0 Rep: 1 Quality: Low Completeness: 60%

Your current approach works, but it's manual and breaks introspection (help(f1) won't show the right signature). Here's the cleaner pattern:

python

import functools

def commoncore(func): """Decorator that adds conditional logic based on the wrapped function's name.""" @functools.wraps(func) # Preserves metadata (name, docstring, signature) def wrapper(a=None, b=None, c=3, *args, **kwargs): # Your conditional logic using func.name if func.name == 'f1': # f1-specific behavior print(f"Running f1 logic with a={a}, b={b}") elif func.name == 'f2': # f2-specific behavior print(f"Running f2 logic with c={c}")

# Common code here result = a + b + c if a and b else c return result return wrapper

@common
core def f1(a=None, b=None, c=3): """Documentation for f1.""" pass # Body handled by decorator

@common_core def f2(a=None, b=None, c=3): """Documentation for f2.""" pass

Usage

print(f1(a=1, b=2, c=5)) # Runs f1 logic print(f2(c=10)) # Runs f2 logic

Introspection still works

print(f1.name) # 'f1' print(f1.doc) # 'Documentation for f1.' help(f1) # Shows correct signature