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

2024-09-28 13:19:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我无法让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)

Tags: nameinpytestimportobjtypeit
1条回答
网友
1楼 · 发布于 2024-09-28 13:19:40

mypy失败的原因与数据类或数据类json无关。如果您尝试简化示例,使所有对象都是常规对象,您仍然会得到相同的错误

这是因为不幸的是,您正试图将TypeVar用于它们从未打算做的事情

TypeVar用于类定义或函数定义:它们允许您“捕获”用户提供的类型值,并在类定义/函数定义的其他部分中重用。每次用户实际尝试使用您的类或函数时,都会执行此“捕获”或“匹配”

但是由于items2class不是泛型类或函数的一部分,mypy最终会合理地抱怨您试图在您想要使用它的上下文之外使用TypeVar

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

如果您想要更精确的类型提示,例如,让mypy了解在使用dict时键“redshift”正好对应于RedshiftItem,您可以尝试使用TypedDicts。但我不相信这在代码的上下文中会有帮助

相关问题 更多 >

    热门问题