Существует функция ( f ), которая использует сигнатуру функции ( g ), которая принимает известный первый набор аргументов и любое количество аргументов ключевого слова **kwargs
. Есть ли способ включить **kwargs
в сигнатуру типа ( g ), которая описана в ( f )?
Например:
from typing import Callable, Any
from functools import wraps
import math
def comparator(f: Callable[[Any, Any], bool]) -> Callable[[str], bool]:
@wraps(f)
def wrapper(input_string: str, **kwargs) -> bool:
a, b, *_ = input_string.split(" ")
return f(eval(a), eval(b), **kwargs)
return wrapper
@comparator
def equal(a, b):
return a == b
@comparator
def equal_within(a, b, rel_tol=1e-09, abs_tol=0.0):
return math.isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol)
# All following statements should print `True`
print(equal("1 1") == True)
print(equal("1 2") == False)
print(equal_within("5.0 4.99998", rel_tol=1e-5) == True)
print(equal_within("5.0 4.99998") == False)
Функция comparator
упаковывает свой аргумент f
с wrapper
, который использует ввод для f
в виде строки, анализирует ее и оценивает это с использованием f
. В этом случае Pycharm выдает предупреждение, что return f(eval(a), eval(b), **kwargs)
вызывает f
с неожиданным аргументом **kwargs
, который не соответствует ожидаемой подписи.
Этот пост в Reddit предлагает добавление Any
или ...
к сигнатуре типа f
, например
f: Callable[[Any, Any, ...], bool]
f: Callable[[Any, Any, Any], bool]
Первый вызывает ошибку TypeError [1], в то время как последняя, похоже, вводит в заблуждение, поскольку f
принимает не менее 2 аргументов, а не ровно 3.
Другой обходной путь - оставить Callable
Аргументы определения открываются с ...
, как f: Callable[..., bool]
, но мне интересно, есть ли более подходящее решение.
TypeError: Callable[[arg, ...], result]: each arg must be a type. Got Ellipsis.