gpt4 book ai didi

python - 需要 **kwargs 的 Callable 的类型注释

转载 作者:行者123 更新时间:2023-12-03 14:32:15 24 4
gpt4 key购买 nike

有一个函数 ( 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包装它的论点 fwrapper ,它使用 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] ,但我想知道是否有更合适的解决方案。
  • TypeError: Callable[[arg, ...], result]: each arg must be a type. Got Ellipsis.
  • 最佳答案

    tl;博士: Protocol 可能是已实现的最接近的功能,但仍不足以满足您的需求。见 this issue详情。

    完整答案:
    我认为最接近您要求的功能是 Protocol ,它是在 Python 3.8 中引入的(并通过 typing_extensions 向后移植到旧版 Python)。它允许您定义 Protocol描述类型行为的子类,很像其他语言中的“接口(interface)”或“特征”。对于函数,支持类似的语法:

    from typing import Protocol
    # from typing_extensions import Protocol # if you're using Python 3.6

    class MyFunction(Protocol):
    def __call__(self, a: Any, b: Any, **kwargs) -> bool: ...

    def decorator(func: MyFunction):
    ...

    @decorator # this type-checks
    def my_function(a, b, **kwargs) -> bool:
    return a == b

    在这种情况下,任何具有匹配签名的函数都可以匹配 MyFunction类型。
    但是,这不足以满足您的要求。为了使函数签名匹配,函数必须能够接受 任意数量的关键字参数 (即,有一个 **kwargs 参数)。到目前为止,仍然无法指定该函数可以(可选地)采用任何关键字参数。 This GitHub issue讨论了当前限制下的一些可能(尽管冗长或复杂)的解决方案。

    现在,我建议只使用 Callable[..., bool]作为 f 的类型注释.但是,可以使用 Protocol细化包装器的返回类型:
    class ReturnFunc(Protocol):
    def __call__(self, s: str, **kwargs) -> bool: ...

    def comparator(f: Callable[..., bool]) -> ReturnFunc:
    ....
    这消除了 equal_within("5.0 4.99998", rel_tol=1e-5) 处的“意外关键字参数”错误。 .

    关于python - 需要 **kwargs 的 Callable 的类型注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61569324/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com