为什么类型的联合不能解析为Python中受约束的泛型类型?
我有下面的例子为什么类型的联合不能解析为Python中受约束的泛型类型?,python,python-3.x,typing,python-typing,Python,Python 3.x,Typing,Python Typing,我有下面的例子 from typing import Union, TypeVar, Dict, Sequence IdentifierSymbol = TypeVar("IdentifierSymbol", str, int) def f(ids: Sequence[IdentifierSymbol]) -> Dict[int, IdentifierSymbol]: return dict(zip(range(len(ids)), ids)) def
from typing import Union, TypeVar, Dict, Sequence
IdentifierSymbol = TypeVar("IdentifierSymbol", str, int)
def f(ids: Sequence[IdentifierSymbol]) -> Dict[int, IdentifierSymbol]:
return dict(zip(range(len(ids)), ids))
def g(ids: Union[Sequence[int], Sequence[str]]) -> int:
x = f(ids)
return 1
PyLance(我猜在内部使用mypy)抱怨行x=f(ids)
:
我不知道如何解释这一点,但听起来问题是int与str不兼容。但为什么在这种情况下会出现这个问题?我有一个str序列或一个int序列,int和str之间的兼容性从何而来?至于
mypy
,那么在当前版本(0.800)中,由于推导类型变量()的特性,这不起作用:当它的类型从多个类型推导出来时(包括在Union
和Sequence
中使用),它被简化为它们最接近的公共基类型。在这种情况下,当此公共基类型未包含在TypeVar约束列表中时,将出现错误
在将来的版本中,此行为将被禁用
例如:
class A: ...
class B(A): ...
class C(A): ...
T = TypeVar("T")
def foo(var1: T, var2: T) -> T:
return var1
reveal_type(foo(B(), C())) # Revealed type is 'main.A*'
def bar(var: T) -> T:
return var
def baz(var: Union[A, B]):
reveal_type(bar(var)) # Revealed type is 'main.A*'
def qux(var: Sequence[T]) -> T:
return var[0]
def quux(var: Tuple[A, B]):
reveal_type(qux(var)) # Revealed type is 'main.A*'
def quuux(var: Union[Sequence[A], Sequence[B]]):
reveal_type(qux(var)) # Revealed type is 'main.A*'
您需要使用其他类型注释,例如使g
函数也通用。也许有人会建议一个更优雅的解决方案
def g(ids: Sequence[IdentifierSymbol]) -> int:
x = f(ids)
return 1
请注意,mypy失败,这里有一个不同的错误:“f”的类型变量“IdentifierSymbol”的值不能是“object”.IIRC MyPy通过超类型而不是并集解析两种类型可居住的变量。这回答了你的问题吗?@MisterMiyagi-Huh我猜PyLance有自己的类型检查器。对此感到惊讶。很可能并集[Sequence[int],Sequence[str]]解析为Sequence[object]或者类似的东西,然后什么也找不到。哦,这很有趣,所以基本上我的并集[Sequence[int],Sequence[str]]变成了Sequence[object]或者诸如此类?奇怪。如果我重载初始函数而不是使用TypeVar,看起来也会发生这种情况,所以我猜Union正在做一些奇怪的事情?遗憾的是,如果我在函数签名中只使用一次TypeVar,PyLance不喜欢它。但它确实会使函数体中的类型警告消失。“遗憾的是,如果我在函数签名中只使用一次TypeVar,PyLance不喜欢。”这条规则对我来说有些模糊。我会通过
#type:ignore
禁用它
def g(ids: Sequence[IdentifierSymbol]) -> int:
x = f(ids)
return 1