今天我深入研究了Liskov替换原则和协变/逆变。
我卡在以下两种方式的区别上:
T = TypeVar("T", bound=Union[A, B])
T = TypeVar("T", A, B, covariant=True)
#1的理解
TypeVar('T', A, B)和TypeVar('T', bound=Union[A, B])的区别
这个答案清楚地说明了T
可以是:
Union[A, B]
(或任何A
和B
的子类型的联合,例如Union[A, BChild]
)A
(或A
的任何子类型)B
(或B
的任何子类型)
这对我来说很有道理。
我对#2的理解存在缺陷
MyPy不允许受限制的TypeVar协变吗?定义具有受限但协变键值类型的通用字典
重新提到bound=Union[A, B]
情况,但没有涉及选项#2 A、B、covariant=True
的含义。
我尝试使用mypy
进行实验,但似乎无法弄清楚。 有人能指出这是什么意思吗?
我认为它的意思是:
A
(或任何A
的子类型)B
(或任何B
的子类型)
(即排除上面的Union
情况)
**编辑**
评论中有人问:
你确定它们实际上是不同的吗?
这里是展示差异的样例代码。错误来自于 mypy==0.770
。
from typing import Union, TypeVar, Generic
class A: pass
class ASub(A): pass
class B: pass
# Case 1... Success: no issues found
# T = TypeVar("T", bound=Union[A, B])
# Case 2... error: Value of type variable "T" of "SomeGeneric" cannot be "ASub"
T = TypeVar("T", A, B, covariant=True)
class SomeGeneric(Generic[T]): pass
class SomeGenericASub(SomeGeneric[ASub]): pass
**编辑2**
最终我在python/mypy #8806:当T_co = TypeVar(“T_co”,A,B,covariant=True)且传递了A的子类时,Generic [T_co]出错
这解决了我一些误解。结果发现TypeVar(“T”,A,B,covariant=True)
并不正确,因为知道值限制A
和B
实际上不是协变的。
只有当它们相关时,使用covariant=True
语法才有用。
mypy
有漏洞。但是,有人能解释一下T = TypeVar("T", A, B, covariant=True)
实际上是什么意思吗?你是说它应该与bound=Union[A, B]
的情况完全相同,如果是的话,为什么呢? - Intrastellar ExplorerA
或B
的类型变量,这恰好是协变的。它不应该与联合边界情况相同。 - user2357112A,ASub,covariant=True
应该拒绝SomeOtherASub
,因为SomeOtherASub
不是ASub
的子类。那么对于T = TypeVar(“T”,A,B,covariant=True)
,然后只使用普通的ASub
进行测试呢?你认为它出错是mypy
的一个错误吗?我仍然不确定A,B,covariant=True
的一般配方。 - Intrastellar Explorer