Python 3.7: класс данных не вызывает `TypeError` для` eq = False` - PullRequest
0 голосов
/ 29 июня 2018

Я пробовал новый 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' 

Есть ли пробел в моем понимании?

Я использую образ докера python/rc-stretch

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Если вы не определите __eq__, __eq__ будет преобразовано в object.__eq__. Вот что происходит, когда вы создаете класс данных с eq=False.

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

0 голосов
/ 29 июня 2018

В 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
...