python-3.x - MyPy 不允许受约束的 TypeVar 协变?使用受约束但协变的键值类型定义通用字典

标签 python-3.x generics covariance mypy

我正在尝试定义一个自定义的通用字典,它的键是 T_key 类型,值是 T_val 类型。
我还想对 T_keyT_val 施加约束,这样 T_key 只能是 AB 或其子类。

我该如何实现?

from typing import TypeVar, Generic

class A: ...
class B: ...

class Asub(A): ...
class Bsub(B): ...

T_key = TypeVar('T_key', A, B, covariant=True)
T_val = TypeVar('T_val', A, B, covariant=True)


class MyDict(Generic[T_key, T_val]): ...


w: MyDict[   A,    B]
x: MyDict[   A, Bsub]
y: MyDict[Asub,    B]
z: MyDict[Asub, Bsub]

当我尝试检查它时,mypy 在 xyz 的注释上给出了错误。只有 w 的注释按预期工作。

generic.py:17: error: Value of type variable "T_val" of "MyDict" cannot be "Bsub"
generic.py:18: error: Value of type variable "T_key" of "MyDict" cannot be "Asub"
generic.py:19: error: Value of type variable "T_key" of "MyDict" cannot be "Asub"
generic.py:19: error: Value of type variable "T_val" of "MyDict" cannot be "Bsub"

我不明白为什么 Asub 不是 T_key 的有效类型,即使指定了 covariant=True

我在这里错过了什么?

mypy version: 0.630

最佳答案

这不是协方差的意思。使用协变类型变量 T 和泛型类 Foo[T]Foo[Subclass] 的实例也被视为 的实例Foo[父类(super class)]。协方差对哪些类型可以替代 T 没有影响。

如果你的B被定义为

class B(A): ...

代替

class B: ...

,则 MyDict[B, B] 类型的值将被静态类型检查器认为是 MyDict[A, A] 类型的有效值,因为协方差.您仍然无法创建 MyDict[ASub, BSub] 类型的值,因为类型变量的唯一有效值是 AB.

您正在寻找的概念是有界 类型变量,使用bound 关键字参数,而不是约束类型变量。看起来你可以指定一个联合作为边界,这让我很惊讶,所以将类型变量声明为

T_key = TypeVar('T_key', bound=Union[A, B])
T_val = TypeVar('T_val', bound=Union[A, B])

应该可以。

关于python-3.x - MyPy 不允许受约束的 TypeVar 协变?使用受约束但协变的键值类型定义通用字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52997754/

相关文章:

python - 为什么在更改超时变量后,Amazon RDS 上的 MySQL 不断使我的连接超时?

java - 通用接口(interface)未按预期运行

Java 使用泛型

.net - .NET Framework 4.0中的类型差异

c# - 通用转换

python-3.x - 出现错误 : 'No module named flask' in VSCode even when I have installed flask

python-3.x - 从一个单词中获取所有可能的 pos 标签

c# - 通用列表性能优化

python - Numpy 协方差

从集合中获取字典的 Pythonic 方法