带有** kwargs的Callable的类型注释

问题描述 投票:2回答:1

有一个函数(f)消耗了一个函数签名(g),该函数签名带有一个已知的第一组参数和任意数量的关键字参数**kwargs 。是否有办法将**kwargs包含在([[f)中描述的(g])的类型签名中?

例如:

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,该参数与预期的签名不匹配。

[This post on Reddit建议在Any的类型签名中添加...f,如

  • f: Callable[[Any, Any, ...], bool]
  • f: Callable[[Any, Any, Any], bool]
  • 前者导致TypeError [1],而后者似乎具有误导性,因为f接受至少 2个参数,而不是3。

另一种解决方法是使Callable args定义与...一样用f: Callable[..., bool]打开,但我想知道是否有更合适的解决方案。

  1. TypeError: Callable[[arg, ...], result]: each arg must be a type. Got Ellipsis.
  2. 有一个函数(f)使用函数签名(g),该函数签名采用已知的第一组参数和任意数量的关键字参数** kwargs。有没有办法将** kwargs包含在...

python typing
1个回答
0
投票

tl; dr:Protocol可能是所实现的最接近的功能,但仍不足以满足您的需求。有关详细信息,请参见Protocol


完整答案:

© www.soinside.com 2019 - 2024. All rights reserved.