It is possible to get signature of a function in python with inspect.signature
.
from typing import overload
import inspect
class Foo:
@overload
def foo(x: int, y: float): ...
@overload
def foo(y: float): ...
def foo(a, b=None):
if b is None:
x, y = 1, a
else:
x, y = a, b
return y / x
print(inspect.signature(Foo.foo)) # (a, b=None)
Is there any way to also see signatures of all overloads of such function?
In this example, I want to get a list [inspect.Signature(x: int, y: float), inspect.Signature(y: float)]
or something close to it.
CodePudding user response:
Before Python 3.11 is released with this PR that adds typing.get_overloads()
, not at runtime, because @overload
does nothing to foo
, it's just a decorator that type checkers understand.
CodePudding user response:
So as @AKX mentioned, there is no way to get the signatures of the overloaded method during runtime from the inspection of this method...
But! We can inspect the source code of the class. So one hacky solution could be:
source_lines, _ = inspect.getsourcelines(Foo)
signatures = []
for l in zip(source_lines):
if 'def foo(' in l:
signatures.append(l.split('(')[1].split(')')[0])
print(signatures)
For your example, this produces:
['x: int, y: float', 'y: float', 'a, b=None']
This code looks directly into the source code of the class and parses it.
If you only want overloads, then you'd need to check for @overload
as well:
source_lines, _ = inspect.getsourcelines(Foo)
signatures = []
for d, f in zip(source_lines, source_lines[1:]):
if '@overload' in d and 'def foo(' in f:
signatures.append(f.split('(')[1].split(')')[0])
print(signatures)
['x: int, y: float', 'y: float']
This is obviously not a fail-proof solution. For instance, this would fail if the signature is divided into multiple lines or contains parentheses (for example tuples or function calls in default values).