Analyzing the __eq__() method, what happens exactly?

Hi,

I’m trying to analyze the eq() method for better understanding what is happening exactly. I hope someone can confirm if my thoughts are right, or correct me if I’m wrong.
I’ve googled of course and found this to be helpful: Python __eq__
Just want to zoom in on these two images on that page:

So my goal is to analize what is happening here.
This is what I came up with:

The init() method is called automatically and the arguments of john and jane are substituted in the parameters of that method. self becomes john (also for jane) so the line ‘self age = age’ becomes ‘john.age = 25’ for object john and for object jane of course ‘jane.age = 25’
In common language: “the property age of object john is 25” (also for jane)

When using == to compare john and jane, the eq method is executed (correct??)

  1. For John: the parameter self becomes john.
    My assumption from this point on is:
    Since the line p1 == p2 contains no arguments for john, python takes jane for the parameter ‘other’, so eq(self, other) becomes eq(john, jane) and the line ‘return self.age = other.age’ becomes ‘return john.age = jane.age’
    Since both properties are the same, a ‘true’ is returned.
    Is this a correct way to describe this?

Thanks in advance!

Hello, @dejong1968, and welcome to Python Foundation Discourse!

When posting code, please copy your original code, then paste and format it, rather than post images of the code. That will enable us to copy it, so we can try it out, and then subsequently answer questions about it more effectively.

One technique for formatting code is to place lines of three back ticks before and after the code, as follows:

```
# example code
print("Monty Python Daily Menu")
for meal in ["breakfast", "lunch", "dinner", "midnight snack"]:
    print(f"Spam for {meal}!")
```

When including inline code within the narrative of a post, also format it. For formatting there, you can surround the code snippet with single back ticks, or select it and and click the </> button.

Essentially, in your example, self represents the john object, and other represents the jane object. But note that in the above quote, you have single = operators where you should have == operators. Also note that since the inline code is not formatted, important details, such as the underscores, do not appear.

1 Like

Hi @dejong1968,

We have two different operations occuring here:

  1. creating two objects;
  2. comparing them for equality (and printing the result).

If the first case, the relevant operations are:

john = Person('john', 'doe', 25)
jane = Person('jane', 'doe', 25)

The two objects basically follow the same set of events.

  1. First, the interpreter finds the Person class, and calls its constructor with three arguments, the strings 'john' (or 'jane'), 'doe', and the integer 25.
  2. If that succeeds, a new object (an instance of the Person class) is returned, and the interpreter assigns that to the variable named john (or jane).

What do I mean by “constructor”?

The constructor is a special method, or in Python’s case, two methods, which are called to create a new instance of the class. Those two methods are the true constructor, the method called __new__, and the “initalizer” __init__.

The __new__ method actually creates the instance in memory; the __init__ method populates it with whatever data you need.

Don’t worry too much about the difference between them. Almost all classes will only use one or the other, and at this early stage in your journey to learn Python, you only need to care about __init__.

So the constructor has created a Person object, or instance, in memory. Now the __init__ method is automatically called to populate it with data.

This sets three attributes of the object. (Synonyms for “attribute” may include properties, members, or instance variables. None of those three are quite accurate for Python, so best to stick with attribute.)

self.first_name = first_name

Here, the variable self represents the current instance being worked on. The part after the dot is the name of the attribute, “first_name”. So we are storing the value of the method parameter “first_name” into the object under the attribute name “first_name”.

And similarly for the other two attributes, “last_name” and “age”.

By the time the __init__ method runs, the instance has three attributes set, using “john”, “doe” and 25. That instance is then saved in the variable called john.

Then the interpreter does it all again for the jane variable.

Now we come to the second operation: comparing the john and jane variables for equality.

First the interpreter locates the objects stored in the variables, which both happen to be Person objects. That will simplify matters.

The the interpreter will look for the special __eq__ method, used for implementing equality tests. It fetches that method by looking at the john variable, so john is “self” and jane is “other”.

(Had you written jane == john instead, then jane would be “self” and john “other”.)

Then the __eq__ method is executed. It ignores the first_name and last_name attributes, and only cares about the age attribute. If the two instances have the same age, then they are considered to be equal.

Earlier, I said that having both objects be Person instances makes things simpler. What if they are different?

If the two objects are not from the same class, say you had a Person being compared with a Robot (say), the rules become more complicated. First the interpreter will ask the Person object if it knows how to compare itself to Robots; if it answers “no”, then the interpreter will try again by asking the Robot if it knows how to handle the equality test.

If that also fails, the interpreter will fall back on the ultimate test: it will check to see if the two arguments are the same object in memory, in which case they are equal, otherwise they are considered unequal.

1 Like

Dear Quercus, thank you for your quick reply and your info about how to post code. This was my first post on this forum. I’ll do this from now on.

Dear Steven,

Thank you for your quick and extensive reply. Even though english is not my native language, your information is very clear and well explained. I conclude that indeed == is the trigger and that my interpretation of the code was right.

A continuation on this is how you can compare multiple attributes at the same time. f.i: check if both lastname and age are the same. I think the & operator is used somehow? Of course I’ll try to figure this out first. Thanks again!

Please take a look at the following documentation from the 6. Expressions page in order to decide whether the & or the and operator should be used:

Then you can write, test, copy, paste, and format the code to show us what you have done.

1 Like

Thanks! I found the answer on w3schools and the following worked:

 def __eq__(self, other):
        return self.first_name == other.first_name and self.age == other.age

… to check on equality of both first_name and age.

Alternative:

def __eq__(self, other):
    if self.first_name == other.first_name and self.age == other.age:
       return True
    else:
        return False
1 Like

Thanks for the formatted code.

Which of the two examples that you posted would you consider preferable?

Would you also like to bring the last_name attribute into the comparison?

1 Like