[The code in the original version was badly messed up. Even after I fixed the code, several highly confusing typos remained in the post. I believe I finally fixed all of them too. Profuse apologies.]
The two calls to alias
below produce different outputs, because the object associated with the variable my_own_id
changes between the two calls:
>>> def my_own_id():
... me = my_own_id
... return id(me)
...
>>> alias = my_own_id
>>> alias()
4301701560
>>> my_own_id = None
>>> alias()
4296513024
What can I assign to me
in the definition of my_own_id
so that its output remains invariant wrt subsequent re-definitions of the my_own_id
variable? (IOW, so that the internal me
variable always refers to the same function object?)
(I can get the current frame (with inspect.currentframe()
), but it contains only a reference to the current code object, not to the current function.)
P.S. The motivation for this question is only to know Python better.
It seems that referring to my_own_id
will look for 'my_own_id'
in the global namespace dictionary, so it will always be the name used on function definition. Since that name can be assigned to different values, the value retrieved can also change. If you make me
a default argument, you can assign it to the function itself at function definition to keep a reference to the actual function.
You could use this decorator which implicitly passes the original function itself as the first argument.
>>> from functools import wraps
>>> def save_id(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(func, *args, **kwargs)
return wrapper
>>> @save_id
def my_own_id(me): # me is passed implicitly by save_id
return id(me)
>>> alias = my_own_id
>>> alias()
40775152
>>> my_own_id = 'foo'
>>> alias()
40775152
Indeed, if you rely only on the function name, if that name is overitten in the global variable space (in the module the function was defined), a reference using the name of the function itslef will fail
The easier, more maintanable way is to write a decorator for that, that would provide a nonlocal
variable containing a reference to the function itself.
from functools import wraps
def know_thyself(func):
@wraps(func):
def new_func(*args, **kwargs):
my_own_id = func
return func(*args, **kwargs)
return new_func
And can be used as:
>>> @know_thyself
... def my_own_id():
... me = my_own_id
... return id(me)
...
There is another possible approach, far from being this clean, using frame introspection and rebuilding a new function re-using the same object code. I had used this on this post about a self-referential lambda expression in Python: http://metapython.blogspot.com.br/2010/11/recursive-lambda-functions.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With