Python 3.7 dataclass是否支持<、>、<=、>=比较运算符?
Transcrypt 3.7.1 Dataclass: Missing Support for <, >, <=, >= Operators
我来帮你梳理下这个问题的根源和解决办法:
为什么会出现这个错误?
你遇到的情况其实是Transcrypt 3.7.1对dataclass的实现限制,再加上对PEP 557(dataclass的官方规范)的小误解:
- 在标准Python中,
@dataclass默认只生成__eq__方法(支持==和!=),排序相关的魔术方法(__lt__、__le__、__gt__、__ge__)需要显式设置order=True才会生成; - 但Transcrypt 3.7.1的dataclass实现还不支持
order=True参数,即使你加上这个参数,也不会自动生成排序相关方法,所以调用<这类运算符时会触发类型错误。
解决办法
这里有两个实用的方案让你实现预期的比较功能:
1. 手动实现排序魔术方法
直接在你的dataclass中定义需要的比较方法,以你的C类为例:
from dataclasses import dataclass @dataclass class C: x: int = 10 def __lt__(self, other): if not isinstance(other, C): return NotImplemented return self.x < other.x def __le__(self, other): if not isinstance(other, C): return NotImplemented return self.x <= other.x def __gt__(self, other): if not isinstance(other, C): return NotImplemented return self.x > other.x def __ge__(self, other): if not isinstance(other, C): return NotImplemented return self.x >= other.x
定义后,c1 < c2这类比较就能正常返回True(因为1 < 2)。
2. 用functools.total_ordering简化代码
如果你不想手动写全四个排序方法,可以借助functools.total_ordering装饰器——它会根据你实现的__lt__和dataclass自动生成的__eq__,自动补齐其他三个排序方法:
from dataclasses import dataclass from functools import total_ordering @total_ordering @dataclass class C: x: int = 10 def __lt__(self, other): if not isinstance(other, C): return NotImplemented return self.x < other.x
这个方案更简洁,Transcrypt 3.7.1对functools.total_ordering的支持是稳定的,如果遇到兼容性问题,再回到手动实现的方案即可。
额外提示
如果后续你还在使用Transcrypt,可以关注它的版本更新——后续版本大概率会完善dataclass的order=True支持,让你能直接和标准Python的用法对齐。
内容的提问来源于stack exchange,提问作者Jacques de Hooge
相关产品推荐
相关产品推荐

