【发布时间】:2020-08-17 11:26:04
【问题描述】:
今天我深入研究了 Liskov 的替换原理和协变/逆变。
我被困在两者之间的区别上:
T = TypeVar("T", bound=Union[A, B])T = TypeVar("T", A, B, covariant=True)
我对#1的理解
Difference between TypeVar('T', A, B) and TypeVar('T', bound=Union[A, B])
This answer 明确指出T 可以:
Union[A, B](或A和B的任何子类型的联合,例如Union[A, BChild])A(或A的任何子类型)B(或B的任何子类型)
这对我来说很有意义。
我的缺陷对#2的理解
重新提到bound=Union[A, B] 的情况,但没有理解选项#2 A, B, covariant=True 的含义。
我尝试过使用mypy,但似乎无法弄清楚。
谁能指出这是什么意思?
我认为意思是:
-
A(或A的任何子类型) -
B(或B的任何子类型)
(又名它不包括上面的 Union 案例)
**编辑**
在cmets中被问到:
你确定它们真的不同吗?
这里是显示差异的示例代码。错误来自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: Generic[T_co] erroring when T_co = TypeVar("T_co", A, B, covariant=True) and passed subclass of A 中询问了这个问题
这消除了我的一些误解。事实证明 TypeVar("T", A, B, covariant=True) 并不正确,知道值限制 A 和 B 实际上并不是协变的。
covariant=True 语法的使用只有在它们相关时才有用。
【问题讨论】:
-
你确定它们真的不同吗?联合本身是协变的,所以对我来说这两个表达式之间的区别并不明显。
-
是的@Samwise 我刚刚编辑了我的问题以添加示例代码来展示差异
-
我认为 mypy 对带有显式选项的类型变量的处理目前存在问题。使用
T = TypeVar("T", A, B),即使没有协方差,它也允许x = SomeGeneric[ASub](),但不允许x: SomeGeneric[ASub]。它根本不允许创建SomeGeneric[ASub]类型的值。 -
好的,所以
mypy可能有问题。谁能至少向我解释一下T = TypeVar("T", A, B, covariant=True)的真正含义?你是说它应该与bound=Union[A, B]的情况相同,如果是,为什么? -
它应该表示只能是
A或B的类型变量,恰好是协变的。它不应该与联合有界的情况相同。
标签: python oop covariance mypy static-typing