Python 具有值限制和联合/可选联合的mypy错误TypeVar无法传递泛型容器类型
所以,下面的例子显然是人为的,但我试图保持一些真实性,以我的实际情况。现在我已经缩减了这个,我确信我遗漏了一些明显的东西。考虑两种类型和限制性联盟:Python 具有值限制和联合/可选联合的mypy错误TypeVar无法传递泛型容器类型,python,python-3.x,generics,mypy,union-types,Python,Python 3.x,Generics,Mypy,Union Types,所以,下面的例子显然是人为的,但我试图保持一些真实性,以我的实际情况。现在我已经缩减了这个,我确信我遗漏了一些明显的东西。考虑两种类型和限制性联盟: from typing import Union, TypeVar, Optional, Generic, overload class Foo: def __init__(self, x: int)-> None: self.x = x def frobnicate(self) -> 'Foo':
from typing import Union, TypeVar, Optional, Generic, overload
class Foo:
def __init__(self, x: int)-> None:
self.x = x
def frobnicate(self) -> 'Foo':
return Foo((self.x + 42) // 42)
class Bar:
def __init__(self, y: int) -> None:
self.y = y
def frobnicate(self) -> 'Bar':
return Bar(self.y + 88)
MyType = TypeVar('MyType', Foo, Bar)
class Container(Generic[MyType]):
val: Optional[MyType]
def __init__(self, val: Optional[MyType]=None) -> None:
self.val = val
def transmogrify(arg: Optional[MyType]) -> Optional[MyType]:
if arg is None:
return None
else:
return arg.frobnicate()
def extract_stuff(x: Optional[int], cont: Container[MyType]) -> Optional[MyType]:
result: Optional[MyType]
if x is None:
result = None
elif x == 88 or x == 42:
result = transmogrify(cont.val)
else:
result = cont.val
return result
当我尝试使用mypy键入check this时,会出现以下错误:
mcve3.py:32: error: Value of type variable "MyType" of "transmogrify" cannot be "Optional[Foo]"
mcve3.py:32: error: Value of type variable "MyType" of "transmogrify" cannot be "Optional[Bar]"
我无法理解这一点。我怀疑这是许多嵌套联合的问题?注意,在我的实际代码中,我使用的是一个自定义的单例枚举Null
,因此无论您看到可选的[Something]
它实际上是联合[Something,Null]
,但我认为这没有什么区别
现在,如果我删除了可选的
,即联合
,这一切都很好:
from typing import Union, TypeVar, Optional, Generic, overload
class Foo:
def __init__(self, x: int)-> None:
self.x = x
def frobnicate(self) -> 'Foo':
return Foo((self.x + 42) // 42)
class Bar:
def __init__(self, y: int) -> None:
self.y = y
def frobnicate(self) -> 'Bar':
return Bar(self.y + 88)
MyType = TypeVar('MyType', Foo, Bar)
class Container(Generic[MyType]):
val: MyType
def __init__(self, val: MyType) -> None:
self.val = val
def transmogrify(arg: MyType) -> MyType:
if arg is None:
return None
else:
return arg.frobnicate()
def extract_stuff(x: int, cont: Container[MyType]) -> MyType:
if x is None:
return None
elif x == 88 or x == 42:
return transmogrify(cont.val)
else:
return cont.val
我在这里错过了什么
注意,我已经尝试抽象出一个基类,并让Foo
和Bar
从一个抽象基类classmytype(metaclass=abc.Meta)
派生出来,但是出现了一个非常类似的错误
编辑以添加:
(py37) Juans-MBP: juan$ mypy --version
mypy 0.620
这似乎是mypy最近修复的一个bug。我可以使用mypy 0.630在您的第一个代码片段中重新编写问题,但无法在master上同时使用mypy 0.641和mypy的最新版本重新编写 我很随便地怀疑这个bug是由修复的,但不确定(而且不想检查,tbh)
您可以监视是否希望收到未来版本的通知,以避免将来出现类似情况。新版本大约每6周到两个月左右发布一次下一个版本将在大约两周左右的时间内发布。@chepner我想我只是有点不知所措,你能详细说明一下吗?因为我使用的是
可选的
,所以受限类型变量如何在联合[MyType,NoneType]
中工作?我不能;我只是还没有仔细阅读你的问题:)这可能已经在mypy的新版本中修复了?我可以使用mypy 0.630重新设置问题,但当我尝试使用mypy 0.641(最新版本)时,问题消失了。@Michael0x2a啊,很高兴知道,谢谢@Michael0x2a哦,天哪!这在我的真实用例中也解决了它!请随时发布答案,以便我可以接受并关闭!你愿意看一看我最近发布的一篇关于类似问题的文章吗?