I was trying out the new dataclasses
in Python 3.7
The dataclass
decorator can be passed arguments to control the dunder functions that are added to the class.
For some reason, the decorator does not seem to raise TypeError
for eq=False
argument.
As per the docs:
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
If I understand correctly, if i pass eq = False
, __eq__
function will not be added, and a TypeError
should be thrown when comparing two instances of the same class. Instead, the eq
parameter seems to have no effect.
@dataclass(eq = False)
class Number:
val: int
a = Number(1)
b = Number(2)
c = Number(1)
a == b
False
a == c
False
The above does not raise TypeError
and always evaluates to 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
The other arguments(eg: order
, repr
) seem to behave as expected
@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'
Is there some gap in my understanding?
I am using docker image python/rc-stretch
In python3.7, given the following dataclass definition
@dataclass(eq=False)
class Number:
val: int
the expected result for Number(1) == Number(1)
is False
. This is correct since setting eq = True
only overrides the default python-object equality function, which just checks for identical references (same as Number(1) is Number(1)
, which might more obviously evaluate to false
) in this case.
The dataclass specification is a bit lacking here. It explains the eq
parameter with
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. [...]
but in order to understand the issue you ran into, you also need to know that the basic python object already comes with an __eq__
function:
>>> class A: pass
...
>>> dir(A())
['__class__', '__delattr__', ... '__eq__', ...] # has __eq__ already
When you don't define __eq__
, __eq__
will resolve to object.__eq__
. That is what's happening when you create a dataclass with eq=False
.
object.__eq__(self, other)
is False unless self is other
, i.e. unless the two are the same object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With