When inspecting at runtime the annotations of a function, one can get the class
annotated for a given argument. For example:
>>> import inspect
>>> inspect.signature(f).parameters['a'].annotation
<class 'int'>
The same can be achieved by doing f.__annotations__
.
However, for reasons I will spare the reader, I would like to get the annotation in readable text format. For example: a: int
will be retrieved as int
, not as <class 'int'>
.
Assume the text should be legal as input to eval
.
I know I can do:
>>> str(inspect.signature(f).parameters['a'])
'a:int'
And then process this string using .split
and such. But I'm wondering if there's a better way.
The annotation
attribute of each parameter object is a class object, so you can simply use the __name__
attribute of the class object to obtain the class name as a string:
import inspect
def f(a: int):
pass
print(inspect.signature(f).parameters['a'].annotation.__name__)
This outputs:
int
But as @chepner pointed out, the annotation
attribute can be a string if it's a forward reference, so if you want your code to be generic, you would have to take that into account. For example:
class A:
def f(self, a: 'A'):
pass
annotation = inspect.signature(A.f).parameters['a'].annotation
print(annotation.__name__ if isinstance(annotation, type) else annotation)
This outputs:
A