I’m trying to create a decorator that extracts the first argument from the function so it can be called later. The reason for this is we may call the function multiple times with only changes to the first argument.
I’m struggling get the typing scheme right where each function has the correct hints and does not drop argument names.
def model[T, R, **P](func: Callable[Concatenate[T, P], R]):
def inner(*args: P.args, **kwargs: P.kwargs):
def freq_dependent(f: T) -> R:
result = func(f, *args, **kwargs)
return np.broadcast_to(result, (f.shape[0], *result.shape[1:]))
return freq_dependent
return inner
@model
def resistor(f: np.ndarray, r: float, z0: float = 50) -> np.ndarray:
y = 1/r
return np.array([y, -y, -y, y]).reshape(1, 2, 2)
The hint for the resistor function is:
(r: float, z0: float = 50) -> ((f: T@model) -> R@model)
The hint for the return function is:
(f: T@model) -> R@model
I can also add the return type to the inner method like this:
def inner(*args: P.args, **kwargs: P.kwargs) -> Callable[[T], R]:
But then I lose the argument names in the hints:
(r: float, z0: float = 50) -> ((ndarray) -> ndarray)
I don’t understand why it’s not resolving the “T” and “R” type variables. It seems like all the information is present to properly resolve the hint. Manually defining the return type for the inner function allows “T” and “R” to resolve, but then you lose the argument names which are arguably more important to the programmer.