如何用Python typing标注带dataclass_json装饰器的类及实例?
针对dataclasses_json的类型标注方案
1. 标注接收带@dataclass_json实例的函数
要让类型检查器识别实例的to_json方法,有两种简洁方式:
方式一:直接使用官方提供的DataClassJsonMixin
@dataclass_json装饰器会自动让类继承DataClassJsonMixin,直接用这个类型标注参数即可:
from dataclasses_json import DataClassJsonMixin def serialize_instance(obj: DataClassJsonMixin) -> str: # 类型检查器会识别obj拥有to_json方法 return obj.to_json(indent=2)
方式二:自定义Protocol(更灵活)
如果需要精准定义方法签名,可通过typing.Protocol自定义协议:
from typing import Protocol class SerializableInstance(Protocol): def to_json(self, *, indent: int | None = None, sort_keys: bool = False) -> str: ... def serialize_instance(obj: SerializableInstance) -> str: return obj.to_json(sort_keys=True)
2. 标注接收带@dataclass_json类的函数
要识别类的from_json类方法,同样有两种实现方式:
方式一:使用官方DataClassJsonMixin
直接标注类类型为Type[DataClassJsonMixin]:
from typing import Type from dataclasses_json import DataClassJsonMixin def deserialize_from_class(cls: Type[DataClassJsonMixin], json_str: str) -> DataClassJsonMixin: # 类型检查器会识别cls拥有from_json类方法 return cls.from_json(json_str)
方式二:自定义带泛型的Protocol(类型更精确)
如果需要让返回值对应具体的数据类类型,结合TypeVar和Protocol实现:
from typing import Protocol, TypeVar, Type # 定义泛型变量,绑定到自定义协议 T = TypeVar('T', bound='DeserializableClass') class DeserializableClass(Protocol): @classmethod def from_json(cls: Type[T], s: str, *, encoding: str = 'utf-8') -> T: ... def deserialize_from_class(cls: Type[T], json_str: str) -> T: # 类型检查器会识别cls的from_json方法,并返回T类型的实例 return cls.from_json(json_str)
这种泛型方式下,传入Person类后,函数返回值会被类型检查器识别为Person实例,而非模糊的父类类型。
内容的提问来源于stack exchange,提问作者davetapley
相关产品推荐
相关产品推荐

