attrs 比较机制完全指南:默认相等性、排序生成与自定义比较(Comparison)
后端【免费下载链接】attrsPython Classes Without Boilerplate项目地址https://gitcode.com/gh_mirrors/at/attrs点击查看免费下载本文围绕 attrs 官方文档 docs/comparison.md 展开系统讲解 attrs 类实例的相等性equality与排序ordering语义默认情况下/!如何生成、orderTrue如何补齐四类排序方法、字段级自定义比较eqFalse、可调用 key 函数以及attrs.cmp_using工具的用法。读完你将掌握 attrs 比较功能的完整配置面并理解其底层代码生成逻辑对应 src/attr/_make.py 与 src/attr/_cmp.py能针对普通对象、NumPy 数组等特殊值对象写出正确的比较策略。默认比较行为类型相同 字段全等attrs 类默认的相等语义非常直观两个实例相等当且仅当它们类型相同、且所有字段值逐一相等。为此attrs 会替你自动编写__eq__与__ne__两个方法from attrs import define define class Point: x: int y: int Point(1, 2) Point(1, 2) # True Point(1, 2) Point(1, 3) # False Point(1, 2) ! Point(1, 3) # True如果你在类装饰器上传入orderTrueattrs 还会额外生成一整套排序方法__le__、__lt__、__ge__、__gt__from attrs import define define(orderTrue) class Point: x: int y: int Point(1, 2) Point(2, 0) # True先比较 x再比较 y Point(2, 0) Point(1, 9) # True生成这些方法之后实例即可直接用于sorted()、min()/max()、bisect等依赖比较运算符的标准库场景无需手写任何样板代码。相等性的实现细节对于相等性attrs 生成的__eq__逻辑分两步先比较两个实例的类型如果other.__class__ is not self.__class__直接返回NotImplemented交由 Python 反射语义决定最终结果通常表现为不相等或抛错类型相同则逐字段用比较所有字段的比较结果用and连接全部相等才返回True。这一生成逻辑的源码位于 src/attr/_make.py 的_make_eq_script()当没有字段参与比较时生成的函数直接return True否则生成return (self.a other.a and self.b other.b and ...)形式的代码。对应的__ne__并非独立实现而是复用__eq__的结果取反——见 src/attr/_make.py 的顶层函数__ne__若__eq__返回NotImplemented则原样转发否则返回not result。排序的实现细节对于排序attrs 的生成策略src/attr/_make.py 的_make_order()同样分三步检查类型if other.__class__ is self.__class__才继续否则返回NotImplemented把每个实例的所有参与排序的字段值打包成元组attrs_to_tuple对两个元组执行对应的比较操作即tuple(self) tuple(other)、、、四种。元组逐元素比较天然遵循先比第一个字段、相等再比下一个的字典序因此 attrs 类实例的排序语义等价于按字段声明顺序做字典序比较这也和sorted()等场景的直觉完全一致。自定义比较排除字段与 init、repr 等特性一样你可以把某个字段从比较中排除出去from attrs import define, field define class C: x: int y: int field(eqFalse) # y 不参与相等性比较 C(1, 2) C(1, 3) # True因为 y 被忽略字段级eqFalse以及等价的orderFalse或旧式cmpFalse表示该字段既不参与/!也不参与///的计算。这在字段携带缓存临时状态对象 id等不影响业务语义的数据时非常实用。值得留意的是底层生成代码在收集字段时做了过滤_make_eq_script()里attrs [a for a in attrs if a.eq]_make_order()里attrs [a for a in attrs if a.order]。也就是说eqFalse的字段根本不会出现在生成的比较表达式里而非参与比较但跳过这也是它性能开销为零的原因。自定义比较可调用 key 函数eq与order除了接受布尔值还可以接受一个可调用对象callable。此时它被当作 key 函数使用语义与sorted(key...)完全一致先对字段值做一次变换再比较变换后的结果。from attrs import define, field define class S: x: str field(eqstr.lower) # 大小写不敏感地比较 S(foo) S(FOO) # True define(orderTrue) class C: x: str field(orderint) # 按整数值排序 C(10) C(2) # True因为 10 2若按字符串字典序则 10 2第二个例子是 key 函数最具说服力的场景字符串10与2的字典序和数值序相反field(orderint)让排序基于整数值从而得到符合数值直觉的结果。从源码看可调用对象会在字段构建阶段被识别并剥离为 key_determine_attrib_eq_order()src/attr/_make.py里的decide_callable_or_boolean()判断——若传入值是 callable则把eq/order置为True同时把该 callable 存入eq_key/order_key。随后相等性生成代码看到eq_key时会把它注入生成函数的全局命名空间并生成key(self.x) key(other.x)形式的表达式src/attr/_make.py排序生成代码则在attrs_to_tuple中对每个字段执行key(value) if key else valuesrc/attr/_make.py。这意味着 key 函数是先映射、后比较只影响比较过程不会改写字段本身的值。用 attrs.cmp_using 为特殊对象定制比较key 函数方案特别适合字段值携带非常规比较属性的对象。典型例子是 NumPy 数组array1 array2返回的是逐元素布尔数组而非标量直接参与比较会产生歧义甚至报错。手写兼容这种语义的 key 函数非常繁琐为此 attrs 提供了现成工具attrs.cmp_using。对于 NumPy 数组官方文档给出的用法是import numpy from attrs import define, field define class C: an_array field(eqattrs.cmp_using(eqnumpy.array_equal))cmp_using会动态构造一个包装类默认类名Comparable可通class_name覆盖该类持有原始值__slots__ [value]并把eq、lt、le、gt、ge五个比较运算委托给你提供的函数。其完整签名与参数语义见 src/attr/_cmp.py参数类型含义eqCallable \| None判定两个对象是否相等的函数如numpy.array_equallt/le/gt/geCallable \| None判定///的函数可只提供部分require_same_typebool为True默认时比较前要求两个值类型相同否则返回NotImplementedclass_namestr生成的包装类类名默认Comparable该工具的内部机制可以从源码与测试还原组合逻辑cmp_using用types.new_class动态创建类只要提供了eq就会注入__eq__与__ne__每提供一个排序函数就注入对应的__lt__/__le__/__gt__/__ge__src/attr/_cmp.py。全序自动补全如果排序函数提供了 13 个而非全部 4 个且同时提供了eqcmp_using会自动应用functools.total_ordering补出剩余方法若只给排序函数而不给eq会抛出ValueErroreq must be define is order to complete ordering from lt, le, gt, ge.——因为total_ordering强依赖__eq__。对应测试见 tests/test_cmp.py 的TestTotalOrderingException。类型约束require_same_typeTrue时比较方法会先调用_check_same_type校验other.value.__class__ is self.value.__class__不满足则返回NotImplementedsrc/attr/_cmp.py。NotImplemented 透传如果用户提供的比较函数返回NotImplemented包装方法也会原样返回NotImplemented把决定权交还给 Python 的反射机制——tests/test_cmp.py 中的TestNotImplementedIsPropagated专门验证了这一行为。cmp_using生成的类既可以像上例那样直接作为eq/order的 key 函数传入field()也可以独立实例化后用于测试tests/test_cmp.py 顶部就用cmp_using(...)构造了EqCSameType、PartialOrderCSameType、FullOrderCSameType等测试夹具分别覆盖只相等、部分排序、全排序三类语义。eq 与 order 相互独立及 cmp 参数的回归使用eq与order时需要特别注意二者是独立设置的。因为attrs.define中order默认是False而attr.s中并非如此attr.s的排序默认跟随相等性。因此在define下只传eqTrue不会产生任何排序方法想让相等与排序同时开启需要分别显式传入eqTrue, orderTrue也可以改用已经为此用途取消弃用的cmp参数一次性同时设置两者field(cmpTrue)等价于field(eqTrue, orderTrue)field(cmpcallable)则同时把该 callable 用作两者的 key 函数。底层参数仲裁逻辑位于 src/attr/_make.py类级_determine_attrs_eq_order与 src/attr/_make.py字段级_determine_attrib_eq_order要点如下若同时传入cmp与eq/order中的任意一个直接抛出ValueErrorDont mix cmp with eq and order.cmp因向后兼容而拥有最高优先级一旦传入就直接决定两者order未指定时默认跟随eq若eqFalse而orderTrue抛出ValueErrororder can only be True if eq is True too.因为排序建立在相等语义之上。边界行为与测试佐证不同类型实例之间的比较行为值得明确生成的__eq__/排序方法对类型不同或require_same_type场景下值类型不同一律返回NotImplemented。对于/!返回NotImplemented后 Python 通常会把结果解释为不相等而对于等排序运算返回NotImplemented通常会向上抛TypeError。这正是 tests/test_cmp.py 中test_ge_different_type注释所强调的差异cls(2) cls(1.0)在require_same_typeTrue时抛TypeError在False时则正常比较。此外cmp_using生成的包装类方法自带稳定的__doc__与__name__如Return a b. Computed by attrs.、__eq__便于调试与内省测试 tests/test_cmp.py 对此做了逐一断言。如果你需要在项目中使用这些特性可参照 tests/test_cmp.py 的测试写法快速验证自己的比较配置是否符合预期。小结attrs 的比较机制可以概括为一条主线与三个定制维度主线是类型相同 字段逐一相等 / 字段元组字典序全部由装饰器自动生成三个维度分别是——用eqFalse/orderFalse排除字段、用 callable 作为 key 函数改变比较基准、用attrs.cmp_using为 NumPy 数组等特殊对象构造可复用的比较包装。配合cmp参数同时开启相等与排序、理解NotImplemented在不同运算符下的行为差异你就能在不写样板代码的前提下精确控制任意 attrs 类的比较语义。赞分享后端【免费下载链接】attrsPython Classes Without Boilerplate项目地址https://gitcode.com/gh_mirrors/at/attrs点击查看免费下载相关推荐C Insights默认比较default生成比较运算符C Insights默认比较default生成比较运算符 还在为手动编写比较运算符而烦恼C20的 default 特性为你带来了革命性的简化本开发工具编译器Learngo 教程彻底搞懂 Go 语言的比较运算符Comparison Operators—— 相等与有序比较的完整指南Learngo 教程彻底搞懂 Go 语言的比较运算符Comparison Operators—— 相等与有序比较的完整指南 比较运算符是 Go 一切条件判示例工程教程Move 语言相等性与比较操作完全指南从 /! 到全类型排序语义Move 语言相等性与比较操作完全指南从 / ! 到全类型排序语义 本指南以 equality and comparison.md https://l区块链Web3上一篇symfony/debug媒体评测专业机构对调试工具的评分下一篇VoxCPM2无分词器TTS系统架构解析与生产级部署指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

InterviewGuide 操作系统面试高频题 41-60 详解:内存分布、页面置换算法与死锁处理全解析

InterviewGuide 操作系统面试高频题 41-60 详解:内存分布、页面置换算法与死锁处理全解析

教程 【免费下载链接】InterviewGuide 🔥🔥「InterviewGuide」是阿秀从校园->职场多年计算机自学过程的记录以及学弟学妹们计算机校招&秋招经验总结文章的汇总,包括但不限于C/C 、Golang、JavaScript、Vue、操作系统、数据结构、计算机…

2026/10/12 3:18:56 阅读更多 →
搜索二叉树C++实现:从插入删除到拷贝析构的完整指南

搜索二叉树C++实现:从插入删除到拷贝析构的完整指南

前阵子帮人调试一个搜索二叉树的模拟实现,代码看起来完整无缺,一运行就崩。排查下来发现是经典的浅拷贝问题:两个对象共享同一棵树,析构时互相抢着释放内存。这类问题在我自己刚开始写搜索二叉树时也踩过不少,所以这篇…

2026/10/12 3:18:56 阅读更多 →
汽车智能制造装备健康管理:从振动分析到预测性维护落地实践

汽车智能制造装备健康管理:从振动分析到预测性维护落地实践

汽车工厂的设备工程师应该都有过这种经历:凌晨两点被电话叫醒,某某工位的机器人报警停机,整条线停着,三分钟一台车的节拍直接归零,白班生产计划全部打乱。等你赶到现场,排查是减速机异响还是电机绕组烧了&a…

2026/10/12 3:18:56 阅读更多 →

最新新闻

Streamyfin 后台下载模块(Background Downloader)深入解析:从 TypeScript API 到 iOS / Android 原生实现

Streamyfin 后台下载模块(Background Downloader)深入解析:从 TypeScript API 到 iOS / Android 原生实现

音视频移动开发 【免费下载链接】streamyfin A modern Jellyfin client built with Expo 项目地址: https://gitcode.com/gh_mirrors/st/streamyfin 点击查看 免费下载 本篇技术指南以 modules/background-downloader/README.md 为骨架,结合 Streamyfin…

2026/10/13 6:00:40 阅读更多 →
10 分钟跑通私有本地 AI 聊天:Open WebUI 从零部署到第一句对话

10 分钟跑通私有本地 AI 聊天:Open WebUI 从零部署到第一句对话

10 分钟跑通私有本地 AI 聊天:Open WebUI 从零部署到第一句对话 【免费下载链接】open-webui User-friendly AI Interface (Supports Ollama, OpenAI API, ...) 项目地址: https://gitcode.com/GitHub_Trending/op/open-webui Open WebUI 是一个开源的自托管…

2026/10/13 6:00:40 阅读更多 →
Kener 状态徽章实战指南:status、uptime 与 Dot 徽章的 URL 语法、查询参数与源码实现解析

Kener 状态徽章实战指南:status、uptime 与 Dot 徽章的 URL 语法、查询参数与源码实现解析

可观测性后端前端运维 【免费下载链接】kener Stunning status pages, batteries included! 项目地址&#xff1a; https://gitcode.com/gh_mirrors/ke/kener 点击查看 免费下载 Kener 内置了三种可直接以 <img> 引入的状态徽章&#xff08;Badge&#xff09;&#xff1…

2026/10/13 6:00:40 阅读更多 →
AUV协同定位与故障检测一体化MATLAB实现

AUV协同定位与故障检测一体化MATLAB实现

简介&#xff1a;本资源是一份面向海洋机器人与水下自主系统研究者的AUV协同定位算法实现方案&#xff0c;聚焦多AUV编队中高精度定位与实时故障检测两大核心挑战&#xff0c;适用于自动化、控制工程及海洋探测方向的研究生、科研人员与算法工程师。压缩包为RAR格式&#xff0c…

2026/10/13 6:00:40 阅读更多 →
Pomotroid 计时器时长键盘输入:从整分钟滑块到 MM:SS 精确设置的完整改造指南

Pomotroid 计时器时长键盘输入:从整分钟滑块到 MM:SS 精确设置的完整改造指南

【免费下载链接】pomotroid :tomato: Simple and visually-pleasing Pomodoro timer 项目地址&#xff1a; https://gitcode.com/gh_mirrors/po/pomotroid 点击查看 免费下载 Pomotroid 是一款基于 Tauri&#xff08;Rust Svelte&#xff09;的番茄钟应用。本篇技术指南围绕其…

2026/10/13 6:00:40 阅读更多 →
OpenClaw 跨平台部署指南:Windows/macOS/Linux 环境搭建避坑全记录

OpenClaw 跨平台部署指南:Windows/macOS/Linux 环境搭建避坑全记录

如果你准备把 OpenClaw 真正用起来&#xff0c;第一道门槛往往不是模型接入&#xff0c;也不是技能配置&#xff0c;而是环境搭建。我见过太多人卡在“装好了但跑不动”“这台能跑换台就崩”的阶段&#xff0c;尤其是在 Windows、macOS、Linux 三套系统之间反复横跳的时候&…

2026/10/13 5:59:40 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目&#xff0c;我最大的感受是&#xff0c;大部分坑不是出在技术前沿&#xff0c;而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节&#xff0c;最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了&#xff0c;很难不碰到舵机控制这道坎。做智能小车要转方向&#xff0c;做机械臂要抬关节&#xff0c;做云台要偏航俯仰&#xff0c;背后都是同一个东西在干活&#xff1a;舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”&#xff1f;——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台&#xff1f;或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜&#xff1f;又或者&#xff0c;在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →