TypeVar 混乱,如何键入回调函数?

时间:2021-05-15 16:40:41

标签: python mypy python-typing

from typing import Tuple, TypeVar, Any

ParamArray = TypeVar("ParamArray", Tuple[Any, ...])

概念是; ParamArray 只是一个值的元组。我有一个功能

def integrate(func, a, b, args=()):
    delta = 0.1
    running_total = 0.
    for x in range(a, b, step=delta):
        running_total += func(x, args) * delta
    return running_total

因此我试图输入它:

def integrate(func:Callable[[float, ParamArray], float], a: float, b: float, args: ParamArray=()) -> float:

试图传达这样一个事实,即 args ParamArray 与传递给 func 的东西相同,因此回调必须能够接受传递的任何 args。

我遇到了一些错误

<块引用>
TypeVar cannot have only a single constraint
Argument 2 to "TypeVar" has incompatible type "object"; expected "Type[Any]"
Variable "typealiases.ParamArray" is not valid as a type

1 个答案:

答案 0 :(得分:1)

首先,由于 ab 将在 range 对象中使用,因此它们应该是 int 而不是浮动。 step= 也应该是 int,所以 delta 也必须是 int

看到这篇文章:click

<块引用>

TypeVar 是一个可以在类型签名中使用的变量,因此您可以 多次引用相同的未指定类型,而 NewType 是 用于告诉类型检查器某些值应该被视为 他们自己的类型。

你得到的错误是因为你不能在 TypeVar 中只有一个约束,在你的例子中只有一个 Tuple

实际上,您希望 func 的参数是某物的 Tuple 实例(或 Tuple 的子类),然后 args 参数是完全相同的元组。这可以使用 bound= 中的 TypeVar 参数来完成。

from typing import Tuple, TypeVar, Any, Callable

ParamArray = TypeVar("ParamArray", bound=Tuple[Any, Any])


def integrate(func: Callable[[ParamArray], float], a: int, b: int,
              args: ParamArray = ()) -> float:
    delta = 1
    running_total = 0.
    for x in range(a, b, step=delta):
        running_total += func(x, args) * delta
    return running_total


def fn1(t: Tuple[int, int]) -> float:
    pass

def fn2(t: Tuple[float, float]) -> float:
    pass

integrate(fn1, 10, 20, (1, 2))      #valid
integrate(fn2, 10, 20, (1.1, 2.2))  #valid
integrate(fn1, 10, 20, (1.1, 2.2))  #invalid

现在在第三种情况下,您可以看到,因为 fn1 接受整数元组,而我们将浮点数元组传递给 args 参数,它会抱怨。 (我知道你会用 fn2 传递整数元组来测试相反的情况,他没有抱怨。那是因为整数也是类型提示中的浮点数)。