输入接口的数据往往是json格式,一般通过 json.loads() 将其转换为字典类型。为了便于内部使用,往往用 dataclass 封装这个字典。
这个过程有时候很简单
@dataclass
class Point:
x: int
y: int
p = {"x": 1, "y": 0}
# 利用**完成参数输入
Point(**p)
如果带有枚举等特殊字段,就需要对字段做特殊处理
from dataclasses import dataclass
from enum import Enum
class Color(Enum):
red = 0
green = 1
blue = 2
@dataclass
class Point:
x: int
y: int
# 增加一个颜色属性,为枚举型
color: Color
p = {"x": 1, "y": 0, "color": 1}
# 这样会出问题
point1 = Point(**p)
# False
print(point1.color == Color.green)
# 这样可行
point2 = Point(**dict(p, color=Color(p['color'])))
# True
print(point2.color == Color.green)
如果dataclass有嵌套的情况,那么处理起来更加麻烦
@dataclass
class Line:
p1: Point
p2: Point
color: Color
line = {
"p1": {"x": 1, "y": 0, "color": 1},
"p2": {"x": 1, "y": 0, "color": 1},
"color": 2,
}
# 这样处理不行
l1 = Line(**line)
# 'dict' object has no attribute 'color'
print(l1.p1.color)
# 必须这样处理
l0 = Line(
p1=Point(**dict(line["p1"], color=Color(line["p1"]['color']))),
p2=Point(**dict(line["p2"], color=Color(line["p2"]['color']))),
color=Color(line['color'])
)
# Color.green
print(l0.p1.color)
这里提供一个解决方案 —— 利用 dacite 库 , 只用一行就能够实现上面繁琐的赋值过程:
from dacite import from_dict, Config
l2 = from_dict(Line, line, Config(cast=[Enum]))
print(l2)
"""
Line(p1=Point(x=1, y=0, color=<Color.green: 1>), p2=Point(x=1, y=0, color=<Color.green: 1>), color=<Color.blue: 2>)
"""
网友评论