python中的 @dataclass

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

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

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

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

传统上:

python 复制代码
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

使用@dataclass

python 复制代码
@dataclass
class Person:
    name: str
    age: int
# 等价于
class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def __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__ 限定字段。

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

python 复制代码
@dataclass
class Config:
    host: str
    port: int = 8080
    debug: bool = field(default=False)

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

python 复制代码
@dataclass
class LogEntry:
    # 必选
    a: str
    b: str
    c: str

    # 可选
    d: Optional[str] = None
    e: Dict[str, Any] = field(default_factory=dict)

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

python 复制代码
from dataclasses import asdict, dataclass, field
from typing import Dict, Any, Optional
@dataclass
class LogEntry:
    # 必选
    a: str
    b: str
    c: str

    # 可选
    d: Optional[str] = None
    e: Dict[str, Any] = field(default_factory=dict)
logentry = LogEntry(
    a='a',
    b='b',
    c='c',
)
logentry_dict = asdict(logentry)
print(logentry_dict)

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

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

完整:

python 复制代码
from dataclasses import asdict, dataclass, field
from typing import Dict, Any, Optional
@dataclass
class LogEntry:
    # 必选
    a: str
    b: str
    c: str

    # 可选
    d: Optional[str] = None
    e: 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)
相关推荐
怒放吧德德7 小时前
Python3基础:基础实战巩固,从“会用”到“活用”
后端·python
Sylvia-girl7 小时前
IO流~~
java·开发语言
aiguangyuan7 小时前
基于BERT的中文命名实体识别实战解析
人工智能·python·nlp
喵手7 小时前
Python爬虫实战:知识挖掘机 - 知乎问答与专栏文章的深度分页采集系统(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·采集知乎问答与专栏文章·采集知乎数据·采集知乎数据存储sqlite
铉铉这波能秀7 小时前
LeetCode Hot100数据结构背景知识之元组(Tuple)Python2026新版
数据结构·python·算法·leetcode·元组·tuple
kali-Myon7 小时前
2025春秋杯网络安全联赛冬季赛-day2
python·安全·web安全·ai·php·pwn·ctf
Re.不晚8 小时前
JAVA进阶之路——无奖问答挑战3
java·开发语言
代码游侠8 小时前
C语言核心概念复习——C语言基础阶段
linux·开发语言·c++·学习
㓗冽8 小时前
60题之内难题分析
开发语言·c++·算法
dingdingfish8 小时前
Bash学习 - 第3章:Basic Shell Features,第5节:Shell Expansions
开发语言·学习·bash