使用 MyPy 针对 TypedDict 验证 `Dict`
Validate `Dict` against `TypedDict` with MyPy
我有几个数据处理器实现了一个接口,其方法“process”接管了处理部分,结果是 returned。结果应该是符合给定结构的字典。这就是我为每个处理器结果定义 TypedDict 的原因。
也许我没有正确理解TypedDict,但我想实现这样的事情:
import abc
from typing import TypedDict
class AProcessorResult(TypedDict):
param1: str
param2: int
class BProcessorResult(TypedDict):
paramA: str
paramB: str
paramC: float
class IProcessor(abc.ABC):
def process(self) -> <Dictionary mypy-checked against processor result structure>:
raise NotImplementedError
class AProcessor(IProcessor):
def process(self) -> <Dictionary mypy-checked against AProcessorResult structure>:
result: AProcessorResult = {
'param1': 'value1',
'param2': 0
}
return result
class BProcessor(IProcessor):
def process(self) -> <Dictionary mypy-checked against BProcessorResult structure>:
result: BProcessorResult = {
'param1': 'value1',
'param2': 1
}
return result
def main() -> None:
aProcessor: AProcessor = AProcessor()
aProcessor.process() # <- Should be successful during the MyPy check
bProcessor: BProcessor = BProcessor()
bProcessor.process() # <- Should fail during the MyPy check
if __name__ == '__main__':
main()
如果我 return 来自“进程”方法的普通字典,MyPy 会抱怨类型不兼容:
Incompatible return value type (got "AProcessorResult", expected
"Dict[Any, Any]")
此时我不想使用数据类,因为字典无论如何都会在后期进行“数据分类”,并且之前需要一些额外的字典处理。
有没有一种巧妙的方法以最抽象和通用的方式实现这一目标?
我正在使用 Python 3.8.
您可以使用泛型来实现这一点。基本上,您将 IProcess 定义为 return 一些通用类型,并定义它使用的具体类型 IProcessor[ConcreteType].
import abc
from typing import TypedDict, Any, Generic, TypeVar
T = TypeVar("T")
class AProcessorResult(TypedDict):
param1: str
param2: int
class BProcessorResult(TypedDict):
paramA: str
paramB: str
paramC: float
class IProcessor(abc.ABC, Generic[T]):
def process(self) -> T:
raise NotImplementedError
class AProcessor(IProcessor[AProcessorResult]):
def process(self) -> AProcessorResult:
result: AProcessorResult = {
'param1': 'value1',
'param2': 0
}
return result
class BProcessor(IProcessor[BProcessorResult]):
def process(self) -> BProcessorResult:
result: BProcessorResult = {
'param1': 'value1',
'param2': 1
}
return result
def main() -> None:
aProcessor: AProcessor = AProcessor()
aProcessor.process() # <- Should be successful during the MyPy check
bProcessor: BProcessor = BProcessor()
bProcessor.process() # <- Should fail during the MyPy check
if __name__ == '__main__':
main()
如果你想更严格并强制 return 类型始终是映射类型,你可以将类型 var 绑定为
Mapping
from typing import Mapping
T = TypeVar("T", bound=Mapping[str, Any])
您可以尝试使用这些解决方案here
我有几个数据处理器实现了一个接口,其方法“process”接管了处理部分,结果是 returned。结果应该是符合给定结构的字典。这就是我为每个处理器结果定义 TypedDict 的原因。 也许我没有正确理解TypedDict,但我想实现这样的事情:
import abc
from typing import TypedDict
class AProcessorResult(TypedDict):
param1: str
param2: int
class BProcessorResult(TypedDict):
paramA: str
paramB: str
paramC: float
class IProcessor(abc.ABC):
def process(self) -> <Dictionary mypy-checked against processor result structure>:
raise NotImplementedError
class AProcessor(IProcessor):
def process(self) -> <Dictionary mypy-checked against AProcessorResult structure>:
result: AProcessorResult = {
'param1': 'value1',
'param2': 0
}
return result
class BProcessor(IProcessor):
def process(self) -> <Dictionary mypy-checked against BProcessorResult structure>:
result: BProcessorResult = {
'param1': 'value1',
'param2': 1
}
return result
def main() -> None:
aProcessor: AProcessor = AProcessor()
aProcessor.process() # <- Should be successful during the MyPy check
bProcessor: BProcessor = BProcessor()
bProcessor.process() # <- Should fail during the MyPy check
if __name__ == '__main__':
main()
如果我 return 来自“进程”方法的普通字典,MyPy 会抱怨类型不兼容:
Incompatible return value type (got "AProcessorResult", expected "Dict[Any, Any]")
此时我不想使用数据类,因为字典无论如何都会在后期进行“数据分类”,并且之前需要一些额外的字典处理。
有没有一种巧妙的方法以最抽象和通用的方式实现这一目标?
我正在使用 Python 3.8.
您可以使用泛型来实现这一点。基本上,您将 IProcess 定义为 return 一些通用类型,并定义它使用的具体类型 IProcessor[ConcreteType].
import abc
from typing import TypedDict, Any, Generic, TypeVar
T = TypeVar("T")
class AProcessorResult(TypedDict):
param1: str
param2: int
class BProcessorResult(TypedDict):
paramA: str
paramB: str
paramC: float
class IProcessor(abc.ABC, Generic[T]):
def process(self) -> T:
raise NotImplementedError
class AProcessor(IProcessor[AProcessorResult]):
def process(self) -> AProcessorResult:
result: AProcessorResult = {
'param1': 'value1',
'param2': 0
}
return result
class BProcessor(IProcessor[BProcessorResult]):
def process(self) -> BProcessorResult:
result: BProcessorResult = {
'param1': 'value1',
'param2': 1
}
return result
def main() -> None:
aProcessor: AProcessor = AProcessor()
aProcessor.process() # <- Should be successful during the MyPy check
bProcessor: BProcessor = BProcessor()
bProcessor.process() # <- Should fail during the MyPy check
if __name__ == '__main__':
main()
如果你想更严格并强制 return 类型始终是映射类型,你可以将类型 var 绑定为
Mapping
from typing import Mapping
T = TypeVar("T", bound=Mapping[str, Any])
您可以尝试使用这些解决方案here