I'm going to answer somewhat differently. A function can refer to its own name in its body and can assign/read values to whatever it finds.
In your case, assuming you want to introspect what a function does, what you want to do is to drive function behavior from what's decorated on its object.
Note that in my example below adder3 - which does what you want and updates from within the function body is not documented from the POV of an introspection tool until it has been executed at least once.
adder2 on the other hand is set up so that it adjusts its behavior according to its annotation and that annotation is visible to introspection tools at all times.
adder4 is added to show one limit of this approach. Referring to the function's name is not a guarantee that you are in fact accessing the function, only whatever the function name resolves to in the globals.
def adder1(x:int = 1, y: int = 2, z: int =3 )->int:
'''This is a doc string'''
return x**2 + y**2
def decorate(**kwds):
""" assign kwds as attributes to the function object """
def actual_decorator(func):
for k, v in kwds.items():
setattr(func, k, v)
return func
return actual_decorator
depends = {"x","y"}
@decorate(_note=f"depends:{depends}", depends=depends)
def adder2(x:int = 1, y: int = 2, z: int =3 )->int:
# a function can totally refer to its name
# and use annotations to dynamically adjust its behavior
depends = adder2.depends
#sum up dependencies
li = []
for key in depends:
v = locals()[key] ** 2
li.append(v)
return sum(li)
def adder3(x:int = 1, y: int = 2, z: int =3 )->int:
""" no note until function execution so this won't allow tools to inspect the module"""
_note = getattr(adder3,"_note",None)
if not _note:
adder3._note = "depends x,y"
return x**2 + y**2
def adder4(x:int = 1, y: int = 2, z: int =3 )->int:
"""there is no guarantee that referring by its own name works"""
print("\n\nadder4.name:", adder4.__name__)
return (x**2 + y**2) * 1000
adder4_saved = adder4
#swap name
adder4 = adder2
for func in [adder1,adder2,adder3,adder4_saved]:
print(f"\n{func.__name__} [note(before)={getattr(func,'_note',None)}] -> {func()} [note(after)={getattr(func,'_note',None)}]")
output:
adder1 [note(before)=None] -> 5 [note(after)=None]
adder2 [note(before)=depends:{'y', 'x'}] -> 5 [note(after)=depends:{'y', 'x'}]
adder3 [note(before)=None] -> 5 [note(after)=depends x,y]
adder4.name: adder2
adder4 [note(before)=None] -> 5000 [note(after)=None]