首页 > 解决方案 > TypeVar 的困惑,如何键入回调函数?

问题描述

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 的事实相同,因此回调必须能够接受传递的任何参数。

我遇到了一些错误

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

标签: pythonmypypython-typing

解决方案


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

看到这个帖子:点击

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

您得到的错误是因为您在 TypeVar 中不能有一个约束,在您的情况下是单个Tuple.

实际上,您希望您的参数是某物func的实例(或 的子类),然后参数是完全相同的元组。这可以使用in 中的参数来完成。TupleTupleargsbound=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通过传递整数元组来测试相反的情况,他不会抱怨。那是因为整数也是类型提示中的浮点数)。


推荐阅读