"Enabling" comparison for classes
Question:
I would like some help on my CSC HW. It is on classes/objects, and it’s a simple class on defining a circle, with the name class Circle(object).
The exact text of the HW (I completed the first two parts of this hw and thus this 3rd part is an expansion on the initial problem):
“””Expand on your Circle class by enabling the comparison of Circle objects using operators such as <, >, >=, <=, ==, and !=, where one Circle is considered “larger” than another if it is in fact larger (i.e., has greater area) the other Circle.
The following code:
A = Circle(2, 5, 1.5)
B = Circle(-6, 1, 1)
print A < B, A != B, A >= B
Should generate this output:
False True True
This is my code for displaying the coordinates and radius of the circle:
class Circle(object):
def __init__(self, x=0, y=0, r=0):
self.x = x
self.y = y
self.r = r
def __str__(self):
return "Circle at (%d , %d). Radius: %f" % (self.x, self.y, self.r)
def main():
print Circle(3, 5, 4.0)
main()
The output of this class is “Circle at (3 , 5). Radius: 4:000000”
We were pointed to a certain page of our textbook with math operators for classes:
eq(), gt(), ge(), lt(), le(), ne(), etc.
So I was thinking, did my professor want something like this?
import math
class Circle(object):
def __init__(self, x=0, y=0, r=0):
self.x = x
self.y = y
self.r = r
def __str__(self):
return "Circle at (%d , %d). Radius: %f" % (self.x, self.y, self.r)
def calcArea(self, r):
self.r = r
return (math.pi)*(r**2)
def __gt__(self, circ1Radius, circ2Radius)
self.circ1Radius = circ1Radius
self.circ2Radius = circ2Radius
r1 = circ1Radius
r2 = circ2Radius
r1 > r2 or r2 > r1
def __ge__(self, circ1Radius, circ2Radius)
#And so on for __lt__(), __le__(), __ne__(), etc
def main():
A = Circle(3,4,1.5)
B = Circle(1,2,5.0)
C = Circle(5,7,7)
D = Circle(9,8,3)
print A < B, B > C, A < C, A >= C
main()
#Output should be "True, False, True, False"
Do we have to make a definition/attribute for each method we want to use in the class? Thank you in advance.
Answers:
Short answer: Yes. You have to define the comparison operators you want to support unless you inherit this behavior from a base class.
Define or override the comparison operators for the class. http://docs.python.org/reference/expressions.html#notin
Looks like you are on the right track, except you only need to pass the second circle object to your comparison. self refers to the first circle object. So self.r would give you the r of the first circle. Also you need to return True or False from the method.
def __gt__(self, circle2):
return self.r > circle2.r
Note that this is just comparing the r’s of the circles.
You can use the total_ordering decorator from functools, which generates all the missing compare methods if you supply __eq__()
and one other.
Given a class defining one or more
rich comparison ordering methods, this
class decorator supplies the rest.
This simplifies the effort involved in
specifying all of the possible rich
comparison operations:
The class must define one of __lt__()
,
__le__()
, __gt__()
, or __ge__()
. In addition, the class should supply an
__eq__()
method.
For Example,
@total_ordering
class Student:
def _is_valid_operand(self, other):
return (hasattr(other, "lastname") and
hasattr(other, "firstname"))
def __eq__(self, other):
if not self._is_valid_operand(other):
return NotImplemented
return ((self.lastname.lower(), self.firstname.lower()) ==
(other.lastname.lower(), other.firstname.lower()))
def __lt__(self, other):
if not self._is_valid_operand(other):
return NotImplemented
return ((self.lastname.lower(), self.firstname.lower()) <
(other.lastname.lower(), other.firstname.lower()))
This isn’t really a response to your question per se, but note that your calcArea(...)
method as is doesn’t really need to be inside the class. (Note that there is no reason to use self
at all in it!)
In fact, what you probably want is a method still inside the class something like
def area(self):
return math.pi*(self.r**2)
so that it actually uses the radius of the circle that you are “in”.
I would like some help on my CSC HW. It is on classes/objects, and it’s a simple class on defining a circle, with the name class Circle(object).
The exact text of the HW (I completed the first two parts of this hw and thus this 3rd part is an expansion on the initial problem):
“””Expand on your Circle class by enabling the comparison of Circle objects using operators such as <, >, >=, <=, ==, and !=, where one Circle is considered “larger” than another if it is in fact larger (i.e., has greater area) the other Circle.
The following code:
A = Circle(2, 5, 1.5)
B = Circle(-6, 1, 1)
print A < B, A != B, A >= B
Should generate this output:
False True True
This is my code for displaying the coordinates and radius of the circle:
class Circle(object):
def __init__(self, x=0, y=0, r=0):
self.x = x
self.y = y
self.r = r
def __str__(self):
return "Circle at (%d , %d). Radius: %f" % (self.x, self.y, self.r)
def main():
print Circle(3, 5, 4.0)
main()
The output of this class is “Circle at (3 , 5). Radius: 4:000000”
We were pointed to a certain page of our textbook with math operators for classes:
eq(), gt(), ge(), lt(), le(), ne(), etc.
So I was thinking, did my professor want something like this?
import math
class Circle(object):
def __init__(self, x=0, y=0, r=0):
self.x = x
self.y = y
self.r = r
def __str__(self):
return "Circle at (%d , %d). Radius: %f" % (self.x, self.y, self.r)
def calcArea(self, r):
self.r = r
return (math.pi)*(r**2)
def __gt__(self, circ1Radius, circ2Radius)
self.circ1Radius = circ1Radius
self.circ2Radius = circ2Radius
r1 = circ1Radius
r2 = circ2Radius
r1 > r2 or r2 > r1
def __ge__(self, circ1Radius, circ2Radius)
#And so on for __lt__(), __le__(), __ne__(), etc
def main():
A = Circle(3,4,1.5)
B = Circle(1,2,5.0)
C = Circle(5,7,7)
D = Circle(9,8,3)
print A < B, B > C, A < C, A >= C
main()
#Output should be "True, False, True, False"
Do we have to make a definition/attribute for each method we want to use in the class? Thank you in advance.
Short answer: Yes. You have to define the comparison operators you want to support unless you inherit this behavior from a base class.
Define or override the comparison operators for the class. http://docs.python.org/reference/expressions.html#notin
Looks like you are on the right track, except you only need to pass the second circle object to your comparison. self refers to the first circle object. So self.r would give you the r of the first circle. Also you need to return True or False from the method.
def __gt__(self, circle2):
return self.r > circle2.r
Note that this is just comparing the r’s of the circles.
You can use the total_ordering decorator from functools, which generates all the missing compare methods if you supply __eq__()
and one other.
Given a class defining one or more
rich comparison ordering methods, this
class decorator supplies the rest.
This simplifies the effort involved in
specifying all of the possible rich
comparison operations:The class must define one of
__lt__()
,
__le__()
,__gt__()
, or__ge__()
. In addition, the class should supply an
__eq__()
method.
For Example,
@total_ordering
class Student:
def _is_valid_operand(self, other):
return (hasattr(other, "lastname") and
hasattr(other, "firstname"))
def __eq__(self, other):
if not self._is_valid_operand(other):
return NotImplemented
return ((self.lastname.lower(), self.firstname.lower()) ==
(other.lastname.lower(), other.firstname.lower()))
def __lt__(self, other):
if not self._is_valid_operand(other):
return NotImplemented
return ((self.lastname.lower(), self.firstname.lower()) <
(other.lastname.lower(), other.firstname.lower()))
This isn’t really a response to your question per se, but note that your calcArea(...)
method as is doesn’t really need to be inside the class. (Note that there is no reason to use self
at all in it!)
In fact, what you probably want is a method still inside the class something like
def area(self):
return math.pi*(self.r**2)
so that it actually uses the radius of the circle that you are “in”.