12

I have a parent dataclass and a sub-dataclass inherits the first class. I've redefined __eq__() method in parent dataclass. But when I compare objects sub-dataclass, it doesn't use the __eq__() method defined in parent dataclass. Why is this happening? How can I fix this?

MWE:

from dataclasses import dataclass


@dataclass
class A:
    name: str
    field1: str = None

    def __eq__(self, other):
        print('A class eq')
        return self.name == other.name


@dataclass
class B(A):
    field2: str = None


b1 = B('b', 'b1')
b2 = B('b', 'b2')
print(b1 == b2)
user2314737
  • 27,088
  • 20
  • 102
  • 114
Nagabhushan S N
  • 6,407
  • 8
  • 44
  • 87

2 Answers2

12

The @dataclass decorator adds a default __eq__ implementation.

If you use

@dataclass(eq=False)

on class B, it will avoid doing that.

See https://docs.python.org/3/library/dataclasses.html

khelwood
  • 55,782
  • 14
  • 81
  • 108
4

By default, the dataclass decorator generates an __eq__ method for the decorated class. To disable this (allowing B to inherit A.__eq__), you need to adjust the decorator.

@dataclass(eq=False)
class B(A):
    field2: str = None
chepner
  • 497,756
  • 71
  • 530
  • 681
  • The generated `__eq__` won't invoke the base class `__eq__`? I'd expect the base class one to check the base class members, and for the derived class one to invoke it to check the base class members then go on to check the derived class ones itself. – Joseph Garvin Jul 06 '23 at 19:32
  • The generated method compares all applicable fields, including those inherited from the base class, instead of calling the base-class method explicitly. – chepner Jul 06 '23 at 19:51
  • When the base class isn't a dataclass it appears to ignore the fields from the base entirely, which seems like a footgun. – Joseph Garvin Jul 07 '23 at 03:18
  • 1
    If the base class isn't a dataclass, it doesn't *have* fields. "Field" isn't just a synonym for "instance attribute" here; it's a specific kind of object that the `dataclass` decorator uses to generate methods. The *user* doesn't need to define `Field` objects explicitly, though they can using `dataclasses.field`: `dataclass` can use the class's annotations and class attributes to define them. – chepner Jul 07 '23 at 15:31
  • All of which is to say, trying to define a dataclass using a non-dataclass base class is probably not a good idea. – chepner Jul 07 '23 at 15:32