因此,以下示例显然是人为设计的,但我试图保持与我的实际情况相吻合。现在,我已经对此进行了细化,我确定我缺少明显的东西。考虑几种类型和受限制的联合:
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进行类型检查时,出现以下错误:
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
,因此无论您在何处看到Optional[Something]
都是Union[Something, Null]
,但我认为这没有什么区别。>
现在,如果我删除Optional
,即Union
,那么一切都很好:
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
我对这里的Union缺少什么?
请注意,我尝试抽象出一个基类,并让Foo
和Bar
从抽象基类class MyType(metaclass=abc.Meta)
派生,但是会弹出一个非常类似的错误。 / p>
编辑以添加:
(py37) Juans-MBP: juan$ mypy --version
mypy 0.620
答案 0 :(得分:2)
这似乎是一个错误,最近已在mypy中修复。我可以使用mypy 0.630在您的第一个代码段中复制该问题,但无法同时使用mypy 0.641和master上最新版本的mypy进行复制。
我非常怀疑https://github.com/python/mypy/pull/5699修复了该错误,但不确定(并不想检查,tbh)。
如果您希望收到将来的版本通知,可以监视mypy's blog,以避免将来出现类似情况。新版本大约每6周到两个月左右发布一次。 -预计下一版将在撰写本文之时大约两周后发布。