我正在编写一个系统来解析包含不同部分的配置文件。每个部分可以有一系列条目,每个条目对于如何解析配置文件中的数据都有不同的逻辑。我已将每个部分封装到一个类中(所有这些部分都派生自基本部分类)。对于每个部分类,我还有一个配套的解析器类,它充当该特定部分的工厂。因此每个解析器都会接收加载的配置文件,解析其节并返回相应的节类类型。
为了允许用户向文件附加更多部分或覆盖基本部分,我需要返回一个包含所有基本解析器的表。这个想法是,用户可以为他们的自定义部分添加更多解析器,或者通过派生特定解析器并根据需要修改解析代码来覆盖特定解析器。这还可以包括从原始部分返回派生类。为此,我需要返回一个字典,将每个解析器的名称映射到相应的解析器。我遇到的问题是弄清楚如何正确输入提示此函数。
这是我正在尝试做的事情的简化示例。一、节课:
@dataclass
class BaseSection:
extra: int = 0
@dataclass
class ASection(BaseSection):
a: int = 0
@dataclass
class BSection(BaseSection):
b: int = 0
现在是解析器:
T = TypeVar("T", bound=BaseSection)
class BaseSectionParser(Generic[T]):
def parse(self, data: str) -> Optional[T]:
if len(data) == 0:
return None
return self._get_data(data)
@abstractmethod
def _get_data(self, data: str) -> T:
pass
class ASectionParser(BaseSectionParser[ASection]):
def _get_data(self, data: str) -> ASection:
ret = ASection()
if data == "a":
ret.a = 1
return ret
class BSectionParser(BaseSectionParser[BSection]):
def _get_data(self, data: str) -> BSection:
ret = BSection()
if data == "b":
ret.b = 2
return ret
最后,这是返回字典的函数:
def get_parsers() -> dict: # <- What do I put here for a type hint?
return {
"a": ASectionParser,
"b": BSectionParser,
}
到目前为止,我已经尝试了以下类型提示:
dict
、dict[str, Any]
、dict[str, type]
:最简单的选项。 Mypy 没有给出错误,但显然它们不包含有关返回的字典是什么的信息。我知道这些有效,但我想知道是否有更好的方法来输入提示。dict[str, BaseSectionParser]
:Mypy 对两行给出相同的错误 error: Dict entry 0 has incompatible type "str": "type[ASectionParser]"; expected "str": "BaseSectionParser[Any]"
dict[str, BaseSectionParser[T]]
:Mypy 也会给出错误,唯一的区别是它将 Any
参数更改为 T
。老实说,我不知道在这里做什么。我如何输入提示以传达该函数返回“从 BaseSectionParser 派生的类型的字符串字典”的概念?
将尝试的类型提示从
dict
扩展到包括 dict[str, type]
和 dict[str, Any]
这个怎么样?
def get_parsers() -> dict[str, type[ASectionParser] | type[BSectionParser]]:
return {
"a": ASectionParser,
"b": BSectionParser,
}
或者...
def get_parsers() -> dict[str, type[BaseSectionParser]]:
return {
"a": ASectionParser,
"b": BSectionParser,
}
这两个选项都会为您提供正确的类型提示,并且不会引发任何错误。