python - Mypy 无法识别具有继承的类类型
问题描述
我无法让 Mypy 在这里识别正确的类型。我要做的就是dict
为类创建一个名称,因此我可以通过提供一个type_name
作为其属性的类来获取该类。也许是因为dataclass
and的dataclasses-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)
尽管我认为我遵循了文档中的说明,但由于某种原因 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 用于他们从未打算做的事情。
TypeVar 旨在用于类定义或函数定义:它们让您“捕获”用户提供的类型的值,并在类定义/函数定义的其他部分重用。每次用户实际尝试使用您的类或函数时,都会执行此“捕获”或“匹配”。
但是由于items2class
不是泛型类或函数的一部分,mypy 最终会正确地抱怨您试图在您打算使用它的上下文之外使用 TypeVar。
值得庆幸的是,在这种情况下,解决方案相对简单:停止使用泛型,而改用 dict 为 type Dict[Str, Type[_BaseDataItem]]
。您的子类一开始都是类型_BaseDataItem
,因此它们是插入此字典的有效项目。
如果你想要更精确的类型提示——例如,让 mypy 明白RedshiftItem
在使用你的 dict 时键“redshift”完全对应——你也许可以尝试使用TypedDicts。但是我不确定这实际上会对您的代码上下文有所帮助。
推荐阅读
- python - 尝试使用python中的变量构建sqlite3参数
- postgresql - 从移动应用程序到 postgres 的最佳实践?
- jsf - 长加载页面和视图状态
- .net - 具有多个客户端的命名管道服务器 (C#)
- laravel - Laravel如何建立Eloquent关系以从child_category表中查找具有相关类别和子类别名称的所有数据?
- powershell - 趋势防毒墙网络版 PowerShell 或批处理脚本
- c++ - CMake:构建和安装本地存储的子模块
- android - 在线性布局中心对齐自定义复选框按钮
- genetic-algorithm - NSGA-II 带机票预订
- javascript - 为什么“响应”在当前上下文中不可用?