I have a decorator that logs the name of the decorated function (among other things).
Is it safe to access the __name__
attribute of the decorated function? Or is there some callable type that doesn't have name that I have not run into yet?
I have a decorator that logs the name of the decorated function (among other things).
Is it safe to access the __name__
attribute of the decorated function? Or is there some callable type that doesn't have name that I have not run into yet?
Answering my own question with a summary of other answers and comments.
Not all callables have __name__
.
Instances of classes that define __call__
may not have a __name__
attribute.
Objects created with functools.partial
do not have a __name__
attribute.
A workaround is to use the three argument getattr
:
name = getattr(callable, '__name__', 'Unknown')
Or use repr(callable)
instead of 'Unknown'
, which would include more information about the callable:
name = getattr(callable, '__name__', repr(callable))
It is pretty safe with functions:
def d():
pass
l = lambda: None
print(d.__name__)
print(l.__name__)
Output:
> d
> <lambda>
You can even safely modify it (for debuging purposes as an example):
l.__name__ = 'Empty function'
print(l.__name__) # Empty function
But beware of classes with __call__
method, they don't have a __name__
attribute.
class C(object):
def __call__(self):
print('call')
print(C().__name__) # AttributeError: 'C' object has no attribute '__name__'
As @felipsmartins pointed out in comments, functools.partial
also doesn't have __name__
attribute. Partial Objects refer to the original function with the member variable func
which let's you get the original function's name like so:my_partial.func.__name__
.
Related: