Python Forum
__eq__ method related problem - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: __eq__ method related problem (/thread-44094.html)



__eq__ method related problem - Tsotne - Mar-08-2025

To keep things brief. Suppose I have a simple Car class with only a single attribute - model:

class Car(object):
    def __init__(self, model):
        self.model = model
    def __eq__(self, other):
        return self.model==other.model
Then I create a Car object:

my_car = Car('Mercedes')
Now suppose I create a simple list object:

my_list = [1, 3.14, 1, 0 , 0, 1, 'some_string', my_car]
Now, I want to count the number of occurrences of 1. This should be 3. However I get the error:

Error:
AttributeError: 'int' object has no attribute 'model
I understand what is going on. The count function behind the scenes makes use of __eq__ function of Car which I defined and since the int object does not have the model attribute, it issues an error. My question is, what is the point of having such an implementation of __eq__ function then? Seems like if any of the object in the list has the __eq__ method overriden, the count method of the list becomes useless.

Wouldn't it be better the count method to be designed in a way that it calls the __eq__ function of the (incoming) int object rather than of those in the list?


RE: __eq__ method related problem - deanhystad - Mar-08-2025

Write a better __eq__().
def __eq__(self, other):
    return isinstance(other, self.__class__) and other.model == self.model



RE: __eq__ method related problem - DeaD_EyE - Mar-08-2025

Edit: I saw it too late. This answer is only related to comparison. tl;dr: Do not compare apples with bananas :-)

For comparison, you need the methods __lt__, __le__, __gt__, __ge__

How can you compare "BMW", "Mercedes", "Audi", "Volkswagen" with a float or integer? How to sort a list with these elements?

Example how you could do it, but shouldn't do it.
from functools import total_ordering


@total_ordering
class Car:
    def __init__(self, model):
        self.model = model

    def __gt__(self, other):
        """
        Always False until you find a solution to compare cars with numbers.
        """
        return False

    def __repr__(self):
        return f'{self.__class__.__name__}(model="{self.model}")'


class Bike(Car):
    pass


my_car = Car("Mercedes")
my_bike = Bike("Citybike")

# removed the str, becuase it does not make any sense to compare text to a number
my_list = [1, 3.14, 1, 0, 0, 1, my_car, my_bike]
my_list.sort()
print(my_list)
Output:
[Bike(model="Citybike"), Car(model="Mercedes"), 0, 0, 1, 1, 1, 3.14]



RE: __eq__ method related problem - Gribouillis - Mar-08-2025

Deanhistad's idea looks like the way to go, however it is seldom a good idea to define an __eq__() method in a class in Python. I think the real question is why do you want to define this method? What's the use case for this? Among other issues, you won't be able to insert Car instances into sets or use them as dictionary keys.


RE: __eq__ method related problem - Tsotne - Mar-08-2025

(Mar-08-2025, 02:21 PM)Gribouillis Wrote: Deanhistad's idea looks like the way to go, however it is seldom a good idea to define an __eq__() method in a class in Python. I think the real question is why do you want to define this method? What's the use case for this? Among other issues, you won't be able to insert Car instances into sets or use them as dictionary keys.

The use case is to make a comparison based on your defined criteria.

c1 = Car('Mercedes')
c2 = Car('BMW')

print(c1 == c2)
In addition I might have a list of various objects.


RE: __eq__ method related problem - Gribouillis - Mar-08-2025

(Mar-08-2025, 07:01 PM)Tsotne Wrote: The use case is to make a comparison based on your defined criteria.

c1 = Car('Mercedes')
c2 = Car('BMW')

print(c1 == c2)
In addition I might have a list of various objects.
If you need to compare cars based on the model, you can simply write the more explicit
print(c1.model == c2.model)
Also if you don't defineCar.__eq__(), the code thelist.count(1) will work because equality defaults to object identity.


RE: __eq__ method related problem - Tsotne - Mar-09-2025

Thank you all. This was a very simplified extract from a more complex implementation. However, I got the useful insights.