mypy错误类型具有值限制和联合的变量/可选无法传递通用容器类型 [英] mypy Error TypeVar with Value Restriction and Union of Unions / Optional Cannot Pass generic container type

查看:96
本文介绍了mypy错误类型具有值限制和联合的变量/可选无法传递通用容器类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,以下示例显然是人为设计的,但我试图保持与我的实际情况相吻合.现在,我已经对此进行了细化,我确信我遗漏了一些明显的东西.考虑几种类型和受限制的联合:

So, the following example is obviously contrived but I tried to keep some verisimilitude to my actual situation. Now that I've whittled this down, I am sure I am missing something obvious. Consider a couple of types and a restricted 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: 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对它进行类型检查时,出现以下错误:

When I try to type-check this with mypy, I get the following errors:

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],但我认为这没有什么区别.

I cannot make sense of this. I suspect it is a problem of the many nested unions? Note, in my actual code, I am using a custom singleton enum Null, so wherever you see Optional[Something] it's actually Union[Something, Null], but I don't think that makes a difference.

现在,如果我删除Optional(即Union),则一切正常:

Now, if I remove the Optional, i.e. Union, it all plays nice:

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的存在遗漏了什么?

What am I missing about Union's here?

请注意,我已经尝试抽象出一个基类,并且让FooBar从抽象基类class MyType(metaclass=abc.Meta)派生,但是会弹出一个非常相似的错误.

Note, I've tried abstracting out a base-class, and having Foo and Bar derive from an abstract base class class MyType(metaclass=abc.Meta), but a very similar error pops up.

编辑以添加:

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

推荐答案

这似乎是一个错误,最近在mypy中已得到修复.通过使用mypy 0.630,我能够在第一个代码段中再现该问题,但在mymaster上同时使用mypy 0.641和最新版本的mypy,都无法再现该问题.

This seems to be a bug that was fixed somewhat recently in mypy. I was able to repro the problem in your first snippet by using mypy 0.630 but was unable to repro using both mypy 0.641 and the latest version of mypy on master.

我非常怀疑该错误是由> https://github.com/python/修复的mypy/pull/5699 ,但不确定(也不想检查,TBH).

I very loosely suspect the bug was fixed by https://github.com/python/mypy/pull/5699, but don't know for certain (and don't feel like checking, tbh).

如果您希望收到有关将来发行版的通知,以避免发生此类情况,您可以监视 mypy的博客将来也有类似的情况.新版本大约每6周到两个月左右发布一次. -下一个版本预计将在撰写本文之时大约两周后发布.

You can monitor mypy's blog if you'd like to be notified of future releases to avoid similar situations in the future. New releases are made roughly every 6 weeks to two months or so. -- the next release is slated to come out in roughly two weeks or so from time of writing.

这篇关于mypy错误类型具有值限制和联合的变量/可选无法传递通用容器类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆