【问题标题】:mypy Error TypeVar with Value Restriction and Union of Unions / Optional Cannot Pass generic container typemypy Error TypeVar with Value Restriction and Union of Unions / Optional Cannot Pass generic container type
【发布时间】:2018-11-28 19:32:42
【问题描述】:

因此,下面的示例显然是人为的,但我试图与我的实际情况保持一些真实性。现在我已经减少了这个,我确信我错过了一些明显的东西。考虑几种类型和一个受限的联合:

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's 在这里我错过了什么?

注意,我尝试抽象出一个基类,并让Foo 和Bar 派生自抽象基类class MyType(metaclass=abc.Meta),但弹出了一个非常相似的错误。

编辑添加:

(py37) Juans-MBP: juan$ mypy --version
mypy 0.620

【问题讨论】:

  • @chepner 我想我只是很密集,你能详细说明一下吗?因为我使用的是Optional,那么受限类型变量如何在Union[MyType, NoneType] 中工作?
  • 我不能;我只是还没有仔细阅读你的问题:)
  • 这可能已在较新版本的 mypy 中得到修复?我能够使用 mypy 0.630 重现问题,但是当我尝试使用 mypy 0.641(最新版本)时问题消失了。
  • @Michael0x2a 呃,很高兴知道,谢谢!
  • @Michael0x2a 哦,伙计!这也在我的真实用例中修复了它!请随时发布作为答案,以便我接受并关闭!

标签: python python-3.x generics mypy union-types


【解决方案1】:

这似乎是最近在 mypy 中修复的一个错误。我能够使用 mypy 0.630 在您的第一个 sn-p 中重现该问题,但无法在 master 上同时使用 mypy 0.641 和最新版本的 mypy 重现。

我非常怀疑该错误已由 https://github.com/python/mypy/pull/5699 修复,但不确定(并且不想检查,tbh)。

如果您希望收到有关未来版本的通知,您可以监控mypy's blog,以避免将来出现类似情况。大约每 6 周到两个月左右发布一次新版本。 -- 下一个版本预计在撰写本文后大约两周左右发布。

【讨论】:

猜你喜欢
  • 2021-04-15
  • 2013-09-11
  • 2022-12-27
  • 1970-01-01
  • 1970-01-01
  • 2016-05-27
  • 1970-01-01
  • 1970-01-01
  • 2022-06-16
相关资源
最近更新 更多