Python 3.7: dataclass не поднимает 'TypeError' для 'eq = False'

Я dataclasses новые dataclasses в Python 3.7

Декоратору dataclass можно передать аргументы для управления функциями dunder, которые добавляются в класс.

По какой-то причине декоратор, похоже, не поднимает TypeError для аргумента eq=False.

Согласно документам:

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

Другие аргументы (например: order, repr), похоже, ведут себя так, как ожидалось

@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 image python/rc-stretch

Ответы

Ответ 1

В python3.7, учитывая следующее определение набора данных

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

ожидаемый результат для Number(1) == Number(1) - False. Это правильно, так как установка eq = True только переопределяет функцию равенства по умолчанию для python-объекта, которая в этом случае просто проверяет идентичные ссылки (то же самое, что и is).


Спецификация набора данных немного отсутствует здесь. Он объясняет параметр eq с помощью

eq: Если true (по умолчанию), будет создан метод __eq__. Этот метод сравнивает класс так, как если бы он был кортежем его полей, по порядку. [...]

но для того, чтобы понять проблему, с которой вы столкнулись, вам также нужно знать, что базовый объект python уже предлагает функцию __eq__:

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

Ответ 2

Когда вы не определяете __eq__, __eq__ решит object.__eq__. Это то, что происходит, когда вы создаете dataclass с eq=False.

object.__eq__(self, other) является False, если только self is other, т.е. если оба они не являются одним и тем же объектом.