当前位置: 首页 > news >正文

[python] dataclass 快速创建数据类

在Python中,dataclass是一种用于快速创建数据类的装饰器和工具。自Python 3.7起,通过标准库中的dataclasses模块引入。它的主要目的是简化定义类来仅存储数据的代码量。通常,这样的类包含多个初始化属性,但没有复杂的方法(尽管你可以添加方法)。使用dataclass装饰器,Python会自动为你生成一些特殊方法,如__init__()、__repr__()、__eq__()等。

定义数据类

from dataclasses import dataclass, asdict
import json@dataclass
class Address:street: strcity: str@dataclass
class User:name: strage: intemail: straddress: Address  # User 包含一个 Address 类型的属性

转换为JSON

由于Address也是一个@dataclass,使用asdict()User实例转换为字典时,Address实例也会被递归地转换为字典。因此,整个转换过程相对直接:

user = User(name="John Doe", age=30, email="john.doe@example.com",address=Address(street="123 Elm Street", city="Gotham"))# 将数据类实例转换为字典,包括嵌套的数据类
user_dict = asdict(user)# 将字典转换为JSON字符串
user_json = json.dumps(user_dict)print(user_json)

处理复杂或特殊类型

如果你的数据类包含不能直接被json.dumps()处理的复杂或特殊类型(如日期时间对象),你可以通过提供一个自定义的处理函数给json.dumps()default参数来解决这个问题。例如,如果User包含一个datetime类型的生日属性,你可以这样做:

from datetime import datetime@dataclass
class User:name: strage: intemail: straddress: Addressbirthday: datetime  # 假设我们添加了一个 datetime 类型的属性def datetime_converter(o):if isinstance(o, datetime):return o.__str__()user = User(name="John Doe", age=30, email="john.doe@example.com",address=Address(street="123 Elm Street", city="Gotham"),birthday=datetime(1990, 1, 1))user_dict = asdict(user)# 使用 default 参数处理 datetime 对象
user_json = json.dumps(user_dict, default=datetime_converter)print(user_json)

通过这种方式,你可以灵活地将包含嵌套@dataclass属性甚至更复杂类型的数据类实例转换成JSON格式。

文章目录

      • 定义数据类
      • 转换为JSON
      • 处理复杂或特殊类型
      • `dataclasses`模块中的重要函数
      • 示例
      • `Field`对象
      • 使用`fields()`函数的示例

dataclasses模块中的重要函数

除了自动生成的方法外,dataclasses模块还提供了一些有用的函数来处理数据类:

  1. fields(class_or_instance)
    返回一个包含数据类的所有Field对象的元组,每个Field对象包含关于字段的信息,如名称、类型和默认值。

  2. asdict(instance, *, dict_factory=dict)
    将数据类实例转换为字典。这对于将数据类实例序列化为JSON非常有用。

  3. astuple(instance, *, tuple_factory=tuple)
    将数据类实例转换为元组。这在需要将数据类实例与其他基于元组的APIs交互时很有用。

  4. is_dataclass(obj)
    检查一个对象是否是数据类或其实例。

  5. replace(instance, **changes)
    创建一个新的数据类实例,其中包含通过changes指定的字段值更改。这在frozen=True(即不可变数据类)的情况下特别有用,因为你不能直接修改字段值。

示例

from dataclasses import dataclass, asdict, astuple, replace@dataclass
class Point:x: inty: intp = Point(10, 20)
print(p)  # 输出: Point(x=10, y=20)p_dict = asdict(p)
print(p_dict)  # 输出: {'x': 10, 'y': 20}p_tuple = astuple(p)
print(p_tuple)  # 输出: (10, 20)p_new = replace(p, x=100)
print(p_new)  # 输出: Point(x=100, y=20)

通过使用dataclass,Python程序员可以更加专注于数据的逻辑,而不是编写重复的方法代码,大大提高了开发效率和代码的可读性。

Field对象

Field对象是dataclasses模块定义的一个类,它包含以下主要属性:

  • name:字符串,字段的名称。
  • type:字段的类型,使用类型注解指定。
  • default:字段的默认值。如果字段没有默认值,则此属性为dataclasses._MISSING_TYPE
  • default_factory:用于生成字段默认值的工厂函数。如果字段没有默认工厂,则此属性为dataclasses._MISSING_TYPE
  • init:一个布尔值,指示是否在自动生成的__init__方法中包含该字段。
  • repr:一个布尔值,指示是否在自动生成的__repr__方法中包含该字段。
  • compare:一个布尔值,指示是否在比较方法中包含该字段(如__eq__)。
  • hash:一个布尔值或None,指示是否在计算哈希值时包含该字段。
  • metadata:一个映射,包含字段的元数据。这是在定义字段时通过metadata参数传递的任意字典。

使用fields()函数的示例

from dataclasses import dataclass, field, fields@dataclass
class Person:name: strage: int = field(default=18, metadata={"description": "Age of the person"})is_student: bool = False# 获取Person数据类的字段信息
for f in fields(Person):print(f"name={f.name}, type={f.type}, default={f.default}, metadata={f.metadata}")# 输出示例:
# name=name, type=<class 'str'>, default=<dataclasses._MISSING_TYPE object at 0x...>, metadata={}
# name=age, type=<class 'int'>, default=18, metadata={'description': 'Age of the person'}
# name=is_student, type=<class 'bool'>, default=False, metadata={}

在这个示例中,我们定义了一个Person数据类,并使用fields()函数遍历其字段,打印出每个字段的名称、类型、默认值和元数据。这种方式特别有用于动态地处理数据类字段,例如在序列化或验证场景中。

相关文章:

  • 第二天 Kubernetes落地实践之旅
  • wsl2使用vscode ssh-remote无法写入文件permission denied解决方法
  • Redis主从复制+Redis哨兵模式+Redis群集模式
  • Redis实现分布式锁
  • Git 基于ED25519、RSA算法生成 SSH 密钥
  • linux 搭建web网站
  • unity学习(45)——选择角色菜单——客户端处理服务器的数据
  • 2.2 mul、div、and、or乘除指令及所有寄存器英文名
  • Flutter 设置每帧绘制结束调用的回调函数
  • RK3568 android11 调试陀螺仪模块 MPU6500
  • flink 设置空闲等待推进水位线,避免子任务上游最小的水位线迟迟未达到触发时间
  • python的正则表达式
  • 《高性能MYSQL》-架构,锁,事务
  • H264的打包,nal,es,pes,pts,dts,ps,ts
  • 第十四届蓝桥杯大赛B组 JAVA 蜗牛 (递归剪枝)
  • 网络传输文件的问题
  • 《Java编程思想》读书笔记-对象导论
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • emacs初体验
  • HomeBrew常规使用教程
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • javascript数组去重/查找/插入/删除
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • Node 版本管理
  • ReactNativeweexDeviceOne对比
  • Service Worker
  • SpringBoot几种定时任务的实现方式
  • ubuntu 下nginx安装 并支持https协议
  • 第2章 网络文档
  • 给Prometheus造假数据的方法
  • 前端存储 - localStorage
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • ​2020 年大前端技术趋势解读
  • ​io --- 处理流的核心工具​
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • # Maven错误Error executing Maven
  • (5)STL算法之复制
  • (arch)linux 转换文件编码格式
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (离散数学)逻辑连接词
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (十八)SpringBoot之发送QQ邮件
  • (推荐)叮当——中文语音对话机器人
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (转)fock函数详解
  • (转)负载均衡,回话保持,cookie
  • (转)我也是一只IT小小鸟
  • .NET CORE Aws S3 使用
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NetCore部署微服务(二)
  • .NET大文件上传知识整理
  • .NET精简框架的“无法找到资源程序集”异常释疑
  • // an array of int
  • @Autowired标签与 @Resource标签 的区别