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

python中的 @dataclass

今天写日志模块时,需求需要将常见的.log格式转为.jsonl格式。由于是封装的标准库logging的东西,原来是简单的字符串formatter格式,现在要转为json格式,同时要传入不同字段并以特定顺序进行打印。

转json-formatter容易,只需要封装logging.Formatter类即可。但是将配置以特定字段顺序打印却很繁琐,要么需要实现类,要么以Dict+大量硬编码实现,同时也伴随着需求的不断变化。最后找到了@dataclassasdict方法进行处理,极大的简化了开发效率。

@dataclass是Python3.7引入的标准库功能,位于模块dataclasses中,是用来简化数据类定义的装饰器。

传统上,定义一个只用来存储数据的类时,需要手动实现__init____repr____eq__等方法。而使用@dataclass能自动生成这些方法。

传统上:

class Person:def __init__(self, name, age):self.name = nameself.age = age

使用@dataclass

@dataclass
class Person:name: strage: int
# 等价于
class Person:def __init__(self, name: str, age: int):self.name = nameself.age = agedef __repr__(self):return f'Person(name={self.name!r}, age={self.age!r})'def __eq__(self, other):return isinstance(other, Person) and self.name == other.name and self.age == other.age

@dataclass的一些参数:

  • init=True:是否自动生成 __init__(默认是)
  • repr=True:是否自动生成 __repr__(默认是)
  • eq=True:是否自动生成 __eq__(默认是)
  • order=True:是否添加比较运算符,如 <>=(需字段支持)
  • frozen=True:是否生成“不可变类”(类似 namedtuple
  • slots=True:是否使用 __slots__ 限定字段。

同时也带默认值和字段控制

@dataclass
class Config:host: strport: int = 8080debug: bool = field(default=False)

@dataclass装饰器要求必须字段必须在可选字段的前面

@dataclass
class LogEntry:# 必选a: strb: strc: str# 可选d: Optional[str] = Nonee: Dict[str, Any] = field(default_factory=dict)

赋值完数据后,使用asdict将其转换为Dict

from dataclasses import asdict, dataclass, field
from typing import Dict, Any, Optional
@dataclass
class LogEntry:# 必选a: strb: strc: str# 可选d: Optional[str] = Nonee: Dict[str, Any] = field(default_factory=dict)
logentry = LogEntry(a='a',b='b',c='c',
)
logentry_dict = asdict(logentry)
print(logentry_dict)

在赋值时,由于存在可选字段没有进行赋值,还是默认值,如果想要去掉默认的可选字段可以使用字典变量:

filtered_log_data = {k: v for k, v in logentry_dict.items() if (v is not None and v != {})}

完整:

from dataclasses import asdict, dataclass, field
from typing import Dict, Any, Optional
@dataclass
class LogEntry:# 必选a: strb: strc: str# 可选d: Optional[str] = Nonee: Dict[str, Any] = field(default_factory=dict)
logentry = LogEntry(a='a',b='b',c='c',
)
logentry_dict = asdict(logentry)
filtered_log_data = {k: v for k, v in logentry_dict.items() if (v is not None and v != {})}
print(filtered_log_data)
http://www.lryc.cn/news/603618.html

相关文章:

  • It学习资源下载
  • LeetCode热题100——155. 最小栈
  • 【JVM】常见的 Java 垃圾回收算法以及常见的垃圾回收器介绍及选型
  • Docker网络技术深度研究与实战手册
  • DisplayPort 与 Display Port Alt模式两者区别解析
  • java导出pdf(使用html)
  • 【LeetCode 热题 100】(二)双指针
  • 【初识数据结构】CS61B中的基数排序
  • 纯血鸿蒙 AudioRenderer+AudioCapturer+RingBuffer 实现麦克风采集+发声
  • Leetcode-3152 特殊数组 II
  • 从字符串中“薅出”最长子串:LeetCode 340 Swift 解法全解析
  • B+树高效实现与优化技巧
  • 如何选择AI IDE?对比Cursor分析功能差异
  • echarts图表点击legend报错问题(折线图)
  • 8.项目起步(2)
  • 数据库02 网页html01 day44
  • 图像增强11种几何变换方法示例
  • 从单机架构到分布式:Redis为何成为架构升级的关键一环?
  • 基于web的在线购物系统的设计与实现/在线商城的设计与实现
  • 架构实战——互联网架构模板(“网络层”技术)
  • MySQL MVCC:并发神器背后的原理解析
  • ElementUI表格 el-table实现自动循环滚动
  • MySQL图解索引篇
  • JavaWeb(苍穹外卖)--学习笔记15(分页查询PageHelper)
  • JavaWeb 入门:JavaScript 基础与实战详解(Java 开发者视角)
  • 一个人开发一个App(数据库)
  • vue3组件通信的几种方法,详解
  • ​第七篇:Python数据库编程与ORM实践
  • Vue 2.0响应式原理深度解析
  • 【C++算法】82.BFS解决FloodFill算法_被围绕的区域