微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Mypy无法识别具有继承的类类型

如何解决Mypy无法识别具有继承的类类型

我无法让Mypy在这里识别正确的类型。我要做的就是为类创建一个dict名称,因此我可以通过提供type_name作为其属性获取该类。也许是因为dataclassdataclasses-json的东西引起了混淆?

# mypy_test.py

from dataclasses import dataclass
from typing import Any,Dict,Type,TypeVar

from dataclasses_json import DataClassjsonMixin


@dataclass
class _BaseDataItem(DataClassjsonMixin):
    name: str  # functions as an ID. Subclasses should NOT modify its value after creation.
    type_name: str
    body: Any = None
    # etc ...


@dataclass
class DatanetItem(_BaseDataItem):
    type_name: str = "datanet"


@dataclass
class RedshiftItem(_BaseDataItem):
    type_name: str = "redshift"


# https://mypy.readthedocs.io/en/stable/kinds_of_types.html#the-type-of-class-objects
IT = TypeVar("IT",bound=_BaseDataItem)

items2classes: Dict[str,Type[IT]] = {
    c.type_name: c for c in (DatanetItem,RedshiftItem)
}


def create_obj(name: str,item_type: str) -> _BaseDataItem:
    klass = items2classes[item_type]
    obj = klass(name)
    return obj

用法示例:

In [1]: import mypy_test as m

In [2]: m.create_obj('123','datanet')
Out[2]: DatanetItem(name='123',type_name='datanet',body=None)

In [3]: m.create_obj('mytable','redshift')
Out[3]: RedshiftItem(name='mytable',type_name='redshift',body=None)

尽管我以为我遵循了in the docs的说明,但由于某些原因,MyPy一直给我这个错误

mypy_test.py:28: error: Type variable "mypy_test.IT" is unbound
mypy_test.py:28: note: (Hint: Use "Generic[IT]" or "Protocol[IT]" base class to bind "IT" inside a class)
mypy_test.py:28: note: (Hint: Use "IT" in function signature to bind "IT" inside a function)
mypy_test.py:35: error: Cannot instantiate type "Type[IT?]"
Found 2 errors in 1 file (checked 1 source file)

解决方法

mypy失败的原因与dataclasses或dataclasses-json无关。如果您尝试简化示例以使所有内容都是常规对象,您仍然会遇到相同的错误。

之所以这样做,是因为不幸的是,您试图将TypeVars用于他们从未打算做的事情。

TypeVars旨在在类定义或函数定义中使用:它们使您可以“捕获”用户提供的类型的值,并在类定义/函数定义的其他部分中重用。每当用户实际尝试使用您的类或函数时,都会执行这种“捕获”或“匹配”。

但是,由于items2class不是泛型类或函数的一部分,因此mypy最终会正确地抱怨您试图在意欲在其中使用它的上下文之外使用TypeVar。

非常感谢,在这种情况下,解决方案相对简单:停止使用泛型,而改用dict为Dict[Str,Type[_BaseDataItem]]类型。首先,您的子类都是_BaseDataItem类型,因此它们是可插入此字典的有效项。

如果您想要更精确的类型提示-例如让mypy理解,使用dict时键“ redshift”正好与RedshiftItem相对应-您也许可以尝试使用TypedDicts。但是我不确定这实际上对您的代码有帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。