jam
jam

Reputation: 529

Override __eq__ with more logic

I have the following python classes

class Message:

    def __init__(self, start_date, attributes):
        self.start_date = start_date
        self.attributes = attributes

    def __eq__(self, other):
        if not isinstance(other, Message):
            return False

        if not self.attributes == other.attrubutes:
            return False

        are_consecutive_dates = False
        self_start_date= datetime.strptime(self.start_date, '%Y-%m-%d')
        other_start_date= datetime.strptime(other.start_date, '%Y-%m-%d')
        
        if not abs(self_start_date.toordinal() - other_start_date.toordinal()) == 1:
            return False

        return True


class Attribute:

    def __init__(self, attribute_a, attribute_b):
        self.attribute_a = attribute_a
        self.attribute_b = attribute_b

    def __eq__(self, other):
        if not isinstance(other, Attribute):
            return False

        if not self.attribute_a == other.attribute_a:
            return False

        if not self.attribute_b == other.attribute_b:
            return False

        return True

From a business perspective, two messages are equals if have the same attributes and have consecutive dates

I have two questions:

  1. Is valid to have some business logic inside the __eq__(like the dates are consecutive)?

  2. If the above is valid, I would like to create a set and pass the Messages instances and discard the ones that are equals by the definition I just wrote, so how I need to override the __hash__?

Upvotes: 1

Views: 1494

Answers (1)

John Kugelman
John Kugelman

Reputation: 361977

Messages are equal if they contain consecutive dates? That doesn't seem right. Equality normally has three properties:

  • Reflexive: a == a. This relation isn't reflexive as messages aren't equal to themselves.
  • Symmetric: if a == b then b == a. Your relation is symmetric since you use abs.
  • Transitive: if a == b and b == c then a == c. It's not transitive. Jan 1 and Jan 3 are not consecutive even though both are consecutive with Jan 2.

By violating these properties you can't use your objects in sets or as dictionary keys. You can't usefully implement __hash__ to match this definition of __eq__: a message isn't equal to itself, but its hash will be equal to itself. This will confuse any data structure that uses either method.

Don't use __eq__ for this. It's not the right relation. Make a new method are_consecutive.

Upvotes: 6

Related Questions