У меня есть MeasurementBase
абстрактный родительский класс, который имеет следующие функциональные возможности: (1) public serialize()
& deserialize()
Я хотел бы реализовать общую логику для родительских открытых методов иопределить приватный _serialize()
& _deserialize()
аннотация.
Реализация базового класса выглядит следующим образом:
import json
from abc import ABC, abstractmethod
from typing import Any, Dict, Generic, TypeVar
TMeasurement = TypeVar("TMeasurement")
class MeasurementBase(ABC, Generic[TMeasurement]):
def serialize(self) -> str:
properties: Dict[str, Any] = {}
properties["measurement_name"] = self.__class__.__name__
properties["value"] = self._serialize()
return json.dumps(properties)
@abstractmethod
def _serialize(self) -> Any:
pass # pragma: no cover
@classmethod
def deserialize(cls, json_str: str) -> TMeasurement:
try:
properties = json.loads(json_str)
class_name = properties["measurement_name"]
if cls.__name__ != class_name:
raise KeyError()
return cls._deserialize(properties["value"])
except KeyError:
raise KeyError()
@classmethod
@abstractmethod
def _deserialize(cls, obj: Any) -> TMeasurement:
pass # pragma: no cover
Затем я создал новый подкласс с внутренним состоянием _val
, который реализует абстрактные методы:
class MeasurementBaseMock(MeasurementBase["MeasurementBaseMock"]):
def __init__(self, val: int) -> None:
self._val = val
def _serialize(self) -> Any:
return self._val
@classmethod
def _deserialize(cls, obj: int) -> "MeasurementBaseMock":
return MeasurementBaseMock(obj)
Затем при тестировании выше:
properties = {"value": 324, "measurement_name": MeasurementBaseMock.__name__}
measurement = MeasurementBaseMock.deserialize(json.dumps(properties))
print(measurement._val)
Я получил следующую ошибку:
error: "TMeasurement" has no attribute "_val"
Как аннотировать тип возврата _deserialize
для поддержкипишущая машинка?
Вещи, которые я пытался: - Я пытался использовать TMeasurement = TypeVar("TMeasurement", bound = "MeasurementBase")
- не работал и имел гораздо больше ошибок Mypy.- Я переместил инициализацию всего состояния в родительский класс - этот работал, но я предпочитаю не использовать такой дизайн.- Я также пробовал использовать аннотации cls, но с той же ошибкой.
Примечание: я использую mypy
> mypy --version
mypy 0.660