Reputation: 672
I have declared a class Triangle
in Python which takes base and height as __init__
arguments and has a method area
that computes and returns the area of the triangle. The __eq__
method of the Triangle
class compares the area of the triangles and return the value. The class is defined as below:
class Shape(object):
def area(self):
raise AttributeException("Subclasses should override this method.")
class Triangle(Shape):
def __init__(self, base, height):
"""
base = base of the triangle.
height = height of the triangle
"""
self.base = base
self.height = height
def area(self):
return (self.base * self.height)/2
def __str__(self):
return 'Triangle with base ' + str(self.base) + ' and height ' + str(self.height)
def __eq__(self, other):
"""
Two triangles are equal if their area is equal
"""
return (self.area() == other.area())
Now I ran the program and created two instances to Triangle
t1
and t3
, and gave them different base and height but their area is equal. So t1 == t3
should be True
which is returned as True
only. But strangely, t1 > t3
is also returned as True
, which I don't understand why?
>>> t1 = Triangle(3,4)
>>> t3 = Triangle(2, 6)
>>> t1.area()
6
>>> t3.area()
6
>>> t1 == t3
True
>>> t1 > t3
True
>>> t1 < t3
False
>>>
Upvotes: 5
Views: 4972
Reputation: 33744
According to the docs
If no __cmp__(), __eq__() or __ne__() operation is defined, class instances are compared by object identity (“address”).
Also stated in this answer, the newer versions of python 2 default uses the object's id for comparison.
So you should always define either __gt__
or __lt__
alongside of __eq__
for comparing the way you wanted. And if you want, you can also define __le__
, __ge__
, __ne__
...
One simple thing you can change is:
class Triangle(Shape):
def __init__(self, base, height):
"""
base = base of the triangle.
height = height of the triangle
"""
self.base = base
self.height = height
def area(self):
return (self.base * self.height)/2
def __str__(self):
return 'Triangle with base ' + str(self.base) + ' and height ' + str(self.height)
def __eq__(self, other):
"""
Two triangles are equal if their area is equal
"""
return (self.area() == other.area())
def __gt__(self, other):
"""
This works for both greater than and less than
"""
return (self.area() > other.area())
Upvotes: 2
Reputation: 27333
Although I can't find a source on this, it seems as if Python 2 uses the id
to compare two objects if you don't define the respective magic methods yourself.
Observe:
>>> t1 = Triangle(3, 4)
>>> t3 = Triangle(2, 6)
>>> t1 > t3
False
>>> t1 < t3
True
>>> t1 = Triangle(3, 4)
>>> t1 > t3
True
>>> t1 < t3
False
This behaviour isn't guaranteed as id
doesn't promise you to assign increasing numbers to objects created later, but it does usually seem to work in CPython 2.7, since id
will give you the physical address of the object.
You will observe that before the redefinition of t1
, id(t1) < id(t3)
, while afterwards, the opposite is the case.
Upvotes: 4