恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

attrs 比较机制完全指南:默认相等性、排序生成与自定义比较(Comparison)

  • 首页
  • 资讯中心
  • /
  • attrs 比较机制完全指南:默认相等性、排序生成与自定义比较(Comparison)

相关资讯

InterviewGuide 操作系统面试高频题 41-60 详解:内存分布、页面置换算法与死锁处理全解析 2026/10/12 3:18:54
搜索二叉树C++实现:从插入删除到拷贝析构的完整指南 2026/10/12 3:18:54
通讯录管理系统数据库课程设计:从建表到Java增删改查完整落地 2026/10/12 3:13:53

最新资讯

AI Agent 技能库构建指南:从设计原则到测试落地
大模型工具调用实战:从JSON解析到Function Calling的三种实现
构建可复用Agent技能系统:从架构设计到调度实践
大数据可视化技术原理与性能优化实战指南
mlpack 嵌入式交叉编译实战:从 CMake 模板到目标硬件部署
StackStorm 注册包报错排查:YAML 解析失败(block mapping 缩进问题)

今日推荐

Debian新手入门:从部署到日常操作的完整指南
MongoDB复制集扩缩容实战:从rs.add到选主事故复盘
条形码目标检测数据集实战:从YOLOv8训练到部署

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

attrs 比较机制完全指南:默认相等性、排序生成与自定义比较(Comparison)

发布时间:2026/10/12 3:18:54
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),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号