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
, т.е. если оба они не являются одним и тем же объектом.