Python 3.7:dataclass在eq=False时不会引发TypeError错误

21

我正在尝试使用Python 3.7中的新dataclasses

dataclass装饰器可以传递参数来控制添加到类中的dunder函数。

由于某种原因,装饰器似乎不会对eq=False参数引发TypeError异常。

根据文档:

eq: If true (the default), an __eq__ method will be generated. 
This method compares the class as if it were a tuple of its fields, in order. 
Both instances in the comparison must be of the identical type

如果我理解正确,如果我传递eq = False,则不会添加__eq__函数,并且当比较同一类的两个实例时应该抛出TypeError。相反,eq参数似乎没有任何效果。

@dataclass(eq = False)
class Number:
    val: int

a = Number(1)
b = Number(2)
c = Number(1)

a == b
False

a == c
False

以上代码不会引发TypeError错误,并始终评估为False

@dataclass()
class Number:
    val: int

a = Number(1)
b = Number(2)
c = Number(1)

a
Number(val = 1)

a == b
False

a == c
True

其他参数(如: orderrepr)似乎按预期运作。
@dataclass(order = False, repr = False)
class Number:
    val:int

a = Number(1)
b = Number(2)
c = Number(1)

a
<__main__.Number object at 0x7fe1036c8b38>

a < b
Traceback (most recent call last):                                                                                                          
  File "<stdin>", line 1, in <module>                                                                                                       
TypeError: '<' not supported between instances of 'Number' and 'Number' 

我是否有什么理解上的疏漏?

我正在使用docker镜像python/rc-stretch


你尝试过使用 @dataclass(eq = False, order = False) 来检查第一个案例吗? - RedEyed
@RedEyed 刚刚尝试了一下,仍然可以进行相等性检查,在 < 或 > 时出现 TypeError - xssChauhan
目前在 python3.7 上无法重现,因为一旦我将 eq = False 设置好后,任何使用 == 进行比较的结果都会返回 False。我会查看文档以确定这是否是预期行为。 - Arne
@Arne 没错。我需要编辑这个问题。 - xssChauhan
2个回答

28
在Python3.7中,假设下列数据类定义:
@dataclass(eq=False)
class Number:
    val: int

Number(1) == Number(1)的预期结果为False。这是正确的,因为设置eq = True只会覆盖默认的Python对象相等函数,它仅检查是否具有相同的引用(就像在这种情况下Number(1) is Number(1),可能更明显地评估为false)。


数据类规范在这里有点不足。 它使用以下方式解释了eq参数:

eq:如果为true(默认情况下),则将生成一个__eq__方法。 这个方法以顺序的方式比较类,就好像它是其字段的元组。[...]

但是,为了理解你遇到的问题,您还需要知道基本的Python对象已经带有一个__eq__函数:

>>> class A: pass
...
>>> dir(A())
['__class__', '__delattr__', ... '__eq__', ...]  # has __eq__ already

1
你能否附上上述期望行为的链接? - xssChauhan
1
请参阅文档中的值比较:“等式比较(==!=)的默认行为基于对象的标识。” - Patrick Haugh
@PatrickHaugh 不错的发现,我也搜索过类似的东西,但是没找到 =) - Arne

6
当您没有定义__eq__时,__eq__ 将被解析为 object.__eq__。这就是当您使用eq=False创建数据类时发生的情况。 object.__eq__(self, other)除非self is other,否则为False,即除非两者是同一对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接