缺省参数强制执行类型标识

我有一个自定义的类(其实是简单的包装,用于 heapq),它将接口包装成面向对象的接口,并允许可选的 keycmp 参数。

为了实现类型检查,我引入了 Tv (堆内值的类型)和 Tk 值的 “键 “的类型–即在堆内要比较的东西)。

因此,对 __init__ 看起来是这样的。

from typing import *

Tv = TypeVar('Tv')
Tk = TypeVar('Tk')

class Heap(Generic[Tv, Tk]):
    def __init__(self, initial: Optional[Iterable[Tv]],
                 key: Callable[[Tv], Tk] = lambda x: x, cmp: Callable[[Tk, Tk], bool] = op.lt):
        pass

不幸的是: mypy 本案中的报告和错误。

error: Incompatible default for argument "key" (default has type "Callable[[Tv], Tv]", argument has type "Callable[[Tv], Tk]")

由于规范什么是 Tk 是没有什么用处的,不管是谁要用的。Heap 我试图完全放弃它 — 我做了 Heap 子类 Generic[Tv] 并设置 Tk = Any. 这有一个很好的副作用,即用户的。Heap 就不需要说明 Tk 型,这与 Tv但我失去了所有的类型检查 Tk 在我的实现中。

是否有办法让类型检查保持在 Tk 之内 Heap 并使默认键值为 lambda x: x 不提出一个错误?

编辑:当我试图使 Heap 子类 Generic[Tv] 并保持 Tk = TypeVar('Tk') 我仍然得到了错误

解决方案:

推断的类型 lambda x: xCallable[[Tv], Tv]的类型,因为函数中没有任何东西可以改变 x 的类型,然后再返回它。这违反了类型提示,即参数和返回类型可以任意变化。

修正方法是使用 cast 告知 mypy 默认函数可以根据需要 “改变 “其参数类型。

class Heap(Generic[Tv, Tk]):
    def __init__(self, 
                 initial: Optional[Iterable[Tv]],
                 key: Callable[[Tv], Tk] = lambda x: cast(Tk, x),
                 cmp: Callable[[Tk, Tk], bool] = op.lt):
        pass

然而,这基本上告诉 mypy 你知道你在做什么,如果你有一个。key 函数没有提供,那么 将确保类型为 Tv 实际上可以作为一个类型为 Tk. 一般来说,有 没有 函数类型 Callable[[Tv], Tk] 对于任意类型 TvTk.

本文来自投稿,不代表运维实战侠立场,如若转载,请注明出处:https://www.shizhanxia.com/842.html

(0)
上一篇 2022年6月29日 下午4:01
下一篇 2022年6月29日 下午4:01

相关推荐

发表评论

登录后才能评论