我在python中使用了一个Generic
类,它的实例很少,只是围绕其他类型的实例进行包装:
import random
from typing import Generic
from typing import TypeVar
from typing import Union
T = TypeVar("T", covariant=True)
class Wrapper(Generic[T]):
def __init__(self, value: T) -> None:
self._value = value
@property
def unwrap(self) -> T:
return self._value
def test_union_wrapper() -> None:
def wrapper_union() -> Wrapper[Union[str, int]]:
if random.random() >= 0.5:
return Wrapper("foo")
else:
return Wrapper(42)
# mypy will give an error for this line
w_u: Union[Wrapper[str], Wrapper[int]] = wrapper_union()
在上述代码上运行mypy
将导致:
error: Incompatible types in assignment (expression has type "Wrapper[Union[str, int]]", variable has type "Union[Wrapper[str], Wrapper[int]]")
这似乎是合理的,因为
Wrapper[Union[str, int]]
≮: Wrapper[str]
,以及
Wrapper[Union[str, int]]
≮: Wrapper[int]
而且,正如在PEP483中可以看到的那样:
Union
behaves covariantly in all its arguments. Indeed, as discussed above,Union[t1, t2, ...]
is a subtype ofUnion[u1, u2, ...]
, ift1
is a subtype ofu1
, etc.
但我不同意,因为我知道这一点∀W∈ Wrapper[Union[str, int]]
,w∈ Wrapper[str]
或w∈ Wrapper[int]
,因此,{Union[Wrapper[str], Wrapper[int]]
,不管怎样。我想让mypy
认识到同样的事实,但我不知道如何认识
甚至有一个使用标准库进行识别的例子。如果我在上面的代码中用另一个协变变量Generic
替换Wrapper
,我们得到:
def test_union_type() -> None:
def type_union() -> Type[Union[str, int]]:
if random.random() >= 0.5:
return str
else:
return int
# mypy has no problem with this
w_u: Union[Type[str], Type[int]] = type_union()
这里,mypy
识别函数返回类型Type[Union[str, int]]
等价于变量类型Union[Type[str], Type[int]]
因此,我有两个问题:
Wrapper
的行为与Type
对Union
的行为相同李>Union
的这种行为有名称吗?如果我们将包装器和联合视为类型上的函数,我们可以说它们commute with each other,但不确定在类型理论或Python的上下文中正确的术语是什么李>
我发现了一个对Q1不满意的解决方案,使用mypy插件和以下类型分析器挂钩:
感觉太过分了,但这可能是唯一的办法
相关问题 更多 >
编程相关推荐