Python类结构最佳实践:初始化方法相同仅属性不同的优化方案
优化JSON Schema类的重复初始化代码
问题背景
我用Python的requests模块对接一个JSON格式的API,为了方便处理接口返回的数据,给每个数据Schema都定义了对应的类——类里只声明属性和类型,然后通过一段重复的__init__方法,把JSON数据里的键值对赋值给类的属性。但每个Schema类的初始化代码完全一样,只有属性列表不同,想找更优的设计方式避免重复代码。
重复的类结构示例:
class ClassExample1: attribute1: float attribute2: float attribute3: str def __init__(self, json: dict) -> None: keys = self.__annotations__.keys() for key in keys: self.__setattr__(key, json[key]) class ClassExample2: attribute1: bool attribute2: list def __init__(self, json: dict) -> None: keys = self.__annotations__.keys() for key in keys: self.__setattr__(key, json[key])
解决方案
1. 基类继承(原生Python实现)
把重复的初始化逻辑抽离到一个基类中,所有Schema类都继承这个基类,就能省去重复写__init__的麻烦:
class BaseSchema: def __init__(self, json: dict) -> None: # 遍历当前类的注解属性,从JSON中取值赋值 for attr_name in self.__annotations__.keys(): setattr(self, attr_name, json[attr_name]) # 子类只需声明属性,无需写__init__ class ClassExample1(BaseSchema): attribute1: float attribute2: float attribute3: str class ClassExample2(BaseSchema): attribute1: bool attribute2: list # 使用方式不变 json_data = {"attribute1": True, "attribute2": [1,2,3]} obj = ClassExample2(json_data)
2. 使用dataclasses(Python 3.7+ 标准库)
Python标准库的dataclasses可以自动帮你生成__init__、__repr__等常用方法,代码更简洁:
from dataclasses import dataclass @dataclass class ClassExample1: attribute1: float attribute2: float attribute3: str @dataclass class ClassExample2: attribute1: bool attribute2: list # 使用时直接解包JSON字典即可 json_data = {"attribute1": 1.2, "attribute2": 3.4, "attribute3": "hello"} obj = ClassExample1(**json_data)
dataclasses还支持设置默认值、忽略某些字段、生成字典/元组等扩展功能,完全能覆盖简单的Schema场景。
3. 使用Pydantic(第三方库,推荐复杂场景)
如果需要严格的类型校验、自动类型转换、嵌套Schema支持,Pydantic是Python生态中处理这类问题的行业标准:
from pydantic import BaseModel class ClassExample1(BaseModel): attribute1: float attribute2: float attribute3: str class ClassExample2(BaseModel): attribute1: bool attribute2: list # 自动校验并转换类型,比如字符串转数字 json_data = {"attribute1": "5.6", "attribute2": 7.8, "attribute3": "test"} obj = ClassExample1(**json_data) print(obj.attribute1) # 输出: 5.6(float类型)
Pydantic会自动验证输入数据的合法性,不合法时抛出明确的错误,还支持嵌套模型、可选字段、默认值、JSON序列化/反序列化等高级功能,适合复杂的API对接场景。
总结
- 简单场景:基类继承或dataclasses足够满足需求,无需额外依赖
- 复杂场景(需要校验/转换):优先选择Pydantic,符合Python社区最佳实践
内容的提问来源于stack exchange,提问作者Darren Woodson
相关产品推荐
相关产品推荐

