ex_dataclass
是一款继基于 dataclass 开发的 python 库并且对数据模型的处理更加友好。它通过 Python3的类型注解 特性能轻易的处理 dict 转换成自定义 datao bject (数据对象),从而明确复杂的数据模型,降低维护代码的压力、降低操作复杂数据难度,以及提高代码逻辑清晰度。- 它在配合
Python3 typing
模块的特殊容器的类型注解能实现更多高级功能,如:typing.Type
、typing.Union
;
- 注解类型(支持)
- int
- str
- float
- bool
- dict
- list
- typing.Dict
- typing.List
- typing.Union
- typing.Type
- ex_dataclass cover的类型
- 功能
- 支持
ex_dataclass
类型继承的正反解析; - 支持
typing.List
中ex_dataclass
类型正反解析; - 支持
typing.List
嵌套正反解析,如:{a: [[{a:1, b:2}, {a:3, b:4}]]}
- 支持
typing.Union
和typing.Type
特殊容器类型注解的多态行为,精确匹配字段存在最多ex_dataclass
类 - 支持反向解析下存在冗余字段,并且抛弃该字段
- 支持typing.Union 和 typing.Type 特殊容器类型相互嵌套场景
- 支持纯净的class类型的正反转换解析;
- 支持
ex_dataccass
字段检测校验,通过类型注解获取类后进行值的校验;
pip install ex-dataclass
示例 1
import typing
from ex_dataclass import ex_dataclass, asdict, field, EXPack
data = {
"teams": [
{
"team_name": "Team-A",
"users" : [
{
"name": "zhangsan",
"age" : 18,
},
{
"name": "lisi",
"age" : 18,
}
]
},
{
"team_name": "Team-B",
"users" : [
{
"name": "jack",
"age" : 18,
},
{
"name": "rose",
"age" : 18,
}
]
}
]
}
@ex_dataclass
class User:
# default_factory: 需要给一个类(可callable)
name: str = field(default_factory=str)
# default: 给定一个默认值
age: int = field(default=0)
@ex_dataclass
class Team:
team_name: str = field(default_factory=str)
# 没有值时,我们设置一个list给users字段
users: typing.List[User] = field(default_factory=list)
@ex_dataclass
class AllTeam:
teams: typing.List[Team] = field(default_factory=list)
# 看看TeamUser 接受参数或字典
all_team = AllTeam(**data)
# 可以看到运行结果,所有类型都被转换成对象,对象在python中是非常的友好可以进行全方位自动补全,并且方便维护;
print(all_team)
# AllTeam(teams=[Team(team_name='Team-A', users=[User(name='', age=18), User(name='', age=18)]), Team(team_name='Team-B', users=[User(name='', age=18), User(name='', age=18)])])
print(all_team.teams)
# [Team(team_name='Team-A', users=[User(name='', age=18), User(name='', age=18)]), Team(team_name='Team-B', users=[User(name='', age=18), User(name='', age=18)])]
print(all_team.teams[0].team_name)
print(all_team.teams[0].users)
# Team-A
# [User(name='', age=18), User(name='', age=18)]
print(all_team.teams[0].users[0].name)
# zhangsan
# 重新转回字典
print(asdict(all_team))
# {'teams': [{'team_name': 'Team-A', 'users': [{'name': 'zhangsan', 'age': 18}, {'name': 'lisi', 'age': 18}]}, {'team_name': 'Team-B', 'users': [{'name': 'jack', 'age': 18}, {'name': 'rose', 'age': 18}]}]}
- 看完第一个示例应该能发现
ex_dataclass
对数据转换成对象,全凭的是我们在属性字段后面写的类型注解。通过这样的转换能力,我们就可以摆脱data_dict["a"]["b"]["c"]
这样取值的复杂场景;
示例 2
- 在继承关系中
ex_dataclass
依旧能准确识别你所需要转换的类型。
@ex_dataclass
class Person:
# default_factory: 需要给一个类(可callable)
name: str = field(default_factory=str)
# default: 给定一个默认值
age: int = field(default=0)
height: float = field(default=float)
weight: float = field(default=float)
@ex_dataclass
class PersonDetails:
address: str = field(default_factory=str)
hobbies: typing.List[str] = field(default_factory=list)
phone: str = field(default_factory=str)
# 继承person使其拥有person的属性
@ex_dataclass
class Male(Person):
gender: str = field(default="male")
@ex_dataclass
class Female(Person):
gender: str = field(default="female")
@ex_dataclass
class Jack(Male):
# 当你默认值需要PersonDetails 对象时,可以写入到default_factory, 如果不需要则写dict或None
details: PersonDetails = field(default_factory=PersonDetails)
@ex_dataclass
class Rose(Female):
details: PersonDetails = field(default_factory=dict)
# 最终初始化两个人物,使用参数初始化, 这里并没有给出gender,因为已经设置默认值了
jack = Jack(
name="jack",
age=18,
height=1.80,
weight=125.0,
details={
"address": "xxxx",
"hobbies": ["aa", "bb", "cc"],
"phone" : "123456789"
}
)
# 使用字典初始化
rose = Rose(
name="rose",
age=18,
height=1.680,
weight=98.0,
details={
"address": "xxxx",
"hobbies": ["aa", "bb", "cc"],
"phone" : "987654321"
}
)
print(jack)
print(jack.details.phone)
print(rose)
print(rose.details.phone)
# Jack(name='jack', age=18, height=1.8, weight=125.0, gender='male', details=PersonDetails(address='xxxx', hobbies=['aa', 'bb', 'cc'], phone='123456789'))
# 123456789
# Rose(name='rose', age=18, height=1.68, weight=98.0, gender='female', details=PersonDetails(address='xxxx', hobbies=['aa', 'bb', 'cc'], phone='987654321'))
# 987654321
- 若当前
ex_dataclass
库对你有帮助请给个 🌟 予以支持;
实例 3
- 一段复杂数据的补全演示(留意body)
请移步: 文档
- 可以通过 issue 提出建议或意见。
- EMail: 972367265@qq.com