0

0

Python 值对象在业务建模中的应用

舞夢輝影

舞夢輝影

发布时间:2026-02-23 18:06:31

|

707人浏览过

|

来源于php中文网

原创

业务中不用dataclass直接当值对象,因其默认可变、无值语义、不校验输入;应手写__init__+__eq__+__hash__,确保不可变、构造即校验、相等性仅依赖可哈希字段内容,并将校验逻辑抽离为独立方法。

python 值对象在业务建模中的应用

为什么不用 dataclass 直接当业务实体?

因为 dataclass 默认可变、无值语义、不校验输入——业务里一个订单对象被意外修改字段,或两个相同订单判断不等,都会引发隐蔽逻辑错误。

值对象的核心诉求是:相等性只看字段内容,不可变,构造即校验。Python 原生没内置值对象类型,得自己控住边界。

  • @dataclass(frozen=True) 是最简起点,但冻结后连 __post_init__ 里的字段修正都报错,不适合需要规范化输入的场景(比如把 "2024-01-01" 自动转成 date
  • 真正可控的做法是手写 __init__ + __eq__ + __hash__,显式声明哪些字段参与比较,且只在初始化时做转换和校验
  • 别依赖 __dict__vars() 做序列化,它们会暴露内部实现细节;统一走 asdict() 或自定义 to_dict()

__eq____hash__ 必须同步定义

只重写 __eq__ 不加 __hash__,对象会自动变成不可哈希(TypeError: unhashable type),导致无法放进 set 或当 dict 的 key——这在去重订单项、缓存聚合根状态时很常见。

更麻烦的是,如果字段里含可变类型(如 listdict),即使写了 __hash__,运行时也可能抛 TypeError: unhashable type

立即学习Python免费学习笔记(深入)”;

客客出品专业威客系统KPPW
客客出品专业威客系统KPPW

客客出品专业威客系统KPPW(简称KPPW)是武汉客客团队自主研发的开源系统项目,主要应用于威客模式的在线服务交易平台搭建。KPPW客客出品的专业威客系统,是keke produced professional witkey的缩写。产品业务核心功能是基于任务悬赏交易和用户服务商品交易为主构建一个C2C的电子商务交易平台,其主要交易对象是以用户为主的技能、经验、时间和智慧型商品。经过多年发展,KPP

下载
  • 确保所有参与 __eq__ 判断的字段本身可哈希(优先用 tuplestrintdate 等)
  • 若必须含列表(如地址行),先转成 tuple 再参与比较:tuple(self.lines)
  • 别在 __hash__ 里调用耗时操作(如数据库查询),它可能被频繁调用

业务字段校验不能只靠 __post_init__

很多人以为加个 @dataclass 再写个 __post_init__ 就万事大吉,但这里有两个硬伤:一是异常堆栈指向 __init__ 而非具体字段,二是校验逻辑和领域规则混在一起,难测试、难复用。

比如「手机号必须是中国大陆 11 位数字」这种规则,应该独立成方法,而不是塞进初始化流程里。

  • 把校验逻辑拆到类方法(如 validate_phone(phone: str) -> str),返回标准化后的值,或抛出带字段名的 ValueError
  • __init__ 中调用它,但不要捕获异常——让错误冒泡,业务层才能决定是提示用户还是拒绝创建
  • 避免在 __init__ 中做 I/O 或远程调用,值对象应是纯内存结构

和 Pydantic BaseModel 混用时的坑

不少项目用 Pydantic 做 API 入参校验,再把解析后的 BaseModel 实例直接当业务值对象用——这会导致行为不一致:Pydantic 默认可变、支持字段动态赋值、__eq__ 比较的是所有字段(包括未设置的 None),而业务上往往只关心“有意义的字段”。

更危险的是,Pydantic 的 model_copy() 默认浅拷贝,嵌套模型修改会影响原对象。

  • 别直接继承 BaseModel 当值对象;要么用 BaseModel 只做 DTO,再手动映射到纯 Python 值对象;要么用 BaseModel__slots__ = True + 自定义 __eq__ + __hash__
  • 如果用 Pydantic v2,可用 model_config = ConfigDict(frozen=True, extra='forbid'),但仍需重写 __eq__ 控制相等逻辑
  • 注意 BaseModeldict() 方法默认包含 None 字段,而值对象通常要过滤掉未设置项

值对象真正的复杂点不在代码怎么写,而在“哪些字段算本质属性”。比如「金额」要不要带币种?「地址」要不要标准化到四级行政区?这些不是技术问题,是业务语义的落地——写完代码后,得拉着产品一起对字段定义,否则后面改一次等于重构整个值对象链。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

830

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

580

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

294

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

210

2025.08.29

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

422

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

595

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

422

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

595

2023.08.10

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

1127

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 4.5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号