Point classWe will write a class for a point in a two dimensional Euclidian space ($\mathbb{R}^2$).
We start with the class definition (def) and the constructor (__init__) which defines the creation of a new class instance.
Note:
__init__ have a default values 0.__init__ arguments are numbers.
In [1]:
class Point():
"""Holds on a point (x,y) in the plane"""
def __init__(self, x=0, y=0):
assert isinstance(x, (int, float)) and isinstance(y, (int, float))
self.x = float(x)
self.y = float(y)
In [2]:
p = Point(1,2)
print("point", p.x, p.y)
origin = Point()
print("origin", origin.x, origin.y)
Notice that when we send a Point to the console we get:
In [3]:
p
Out[3]:
Which is not useful, so we will define how Point is represented in the console using __repr__.
In [4]:
class Point():
"""Holds on a point (x,y) in the plane"""
def __init__(self, x=0, y=0):
assert isinstance(x, (int, float)) and isinstance(y, (int, float))
self.x = float(x)
self.y = float(y)
def __repr__(self):
return "Point(" + str(self.x) + ", " + str(self.y) + ")"
In [5]:
Point(1,2)
Out[5]:
Next up we define a method to add two points. Addition is by elements - $(x_1, y_1) + (x_2, y_2) = (x_1+x_2, y_1+y_2)$.
We also allow to add an int, in which case we add the point to a another point with both coordinates equal to the argument value.
In [6]:
class Point():
"""Holds on a point (x,y) in the plane"""
def __init__(self, x=0, y=0):
assert isinstance(x, (int, float)) and isinstance(y, (int, float))
self.x = float(x)
self.y = float(y)
def __repr__(self):
return "Point(" + str(self.x) + ", " + str(self.y) + ")"
def add(self, other):
assert isinstance(other, (int, Point))
if isinstance(other, Point):
return Point(self.x + other.x , self.y + other.y)
else: # other is int, taken as (int, int)
return Point(self.x + other , self.y + other)
In [7]:
Point(1,1).add(Point(2,2))
Out[7]:
In [8]:
Point(1,1).add(2)
Out[8]:
A nicer way to do it is to overload the addition operator + by defining the addition method name to a name Python reserves for addition - __add__ (those are double underscores):
In [9]:
class Point():
"""Holds on a point (x,y) in the plane"""
def __init__(self, x=0, y=0):
assert isinstance(x, (int, float)) and isinstance(y, (int, float))
self.x = float(x)
self.y = float(y)
def __repr__(self):
return "Point(" + str(self.x) + ", " + str(self.y) + ")"
def __add__(self, other):
assert isinstance(other, (int, Point))
if isinstance(other, Point):
return Point(self.x + other.x , self.y + other.y)
else: # other is int, taken as (int, int)
return Point(self.x + other , self.y + other)
In [10]:
Point(1,1) + Point(2,2)
Out[10]:
In [11]:
Point(1,1) + 2
Out[11]:
We want to be a able to compare Points:
In [12]:
Point(1,2) == Point(2,1)
Out[12]:
In [13]:
Point(1,2) == Point(1,2)
Out[13]:
In [14]:
p = Point()
p == p
Out[14]:
In [15]:
Point(1,2) > Point(2,1)
So == checks by identity and > is not defined. Let us overload both these operators:
In [16]:
class Point():
"""Holds on a point (x,y) in the plane"""
def __init__(self, x=0, y=0):
assert isinstance(x, (int, float)) and isinstance(y, (int, float))
self.x = float(x)
self.y = float(y)
def __repr__(self):
return "Point(" + str(self.x) + ", " + str(self.y) + ")"
def __add__(self, other):
assert isinstance(other, (int, Point))
if isinstance(other, Point):
return Point(self.x + other.x , self.y + other.y)
else: # other is int, taken as (int, int)
return Point(self.x + other , self.y + other)
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)
def __gt__(self, other):
return (self.x > other.x and self.y > other.y)
First we check if two points are equal:
In [17]:
Point(1,0) == Point(1,2)
Out[17]:
In [18]:
Point(1,0) == Point(1,0)
Out[18]:
Then if one is strictly smaller than the other:
In [19]:
Point(1,0) > Point(1,2)
Out[19]:
The addition operator + returns a new instance.
Next we will write a method that instead of returning a new instance, changes the current instance:
In [36]:
class Point():
"""Holds on a point (x,y) in the plane"""
def __init__(self, x=0, y=0):
assert isinstance(x, (int, float)) and isinstance(y, (int, float))
self.x = float(x)
self.y = float(y)
def __repr__(self):
return "Point(" + str(self.x) + ", " + str(self.y) + ")"
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)
def __gt__(self, other):
return (self.x > other.x and self.y > other.y)
def __add__(self, other):
assert isinstance(other, (int, Point))
if isinstance(other, Point):
return Point(self.x + other.x , self.y + other.y)
else: # other is int, taken as (int, int)
return Point(self.x + other , self.y + other)
def increment(self, other):
'''this method changes self (add "inplace")'''
assert isinstance(other,Point)
self.x += other.x
self.y += other.y
In [37]:
p = Point(6.5, 7)
p + Point(1,2)
print(p)
p.increment(Point(1,2))
print(p)
In [20]:
Point(5,6) > Point(1,2)
Out[20]:
We now write a method that given many points, checks if the current point is more extreme than the other points.
Note that the argument *points means that more than one argument may be given.
In [21]:
class Point():
"""Holds on a point (x,y) in the plane"""
def __init__(self, x=0, y=0):
assert isinstance(x, (int, float)) and isinstance(y, (int, float))
self.x = float(x)
self.y = float(y)
def __repr__(self):
return "Point(" + str(self.x) + ", " + str(self.y) + ")"
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)
def __lt__(self, other):
return (self.x < other.x and self.y < other.y)
def __add__(self, other):
assert isinstance(other, (int, Point))
if isinstance(other, Point):
return Point(self.x + other.x , self.y + other.y)
else: # other is int, taken as (int, int)
return Point(self.x + other , self.y + other)
def increment(self, other):
'''this method changes self (add "inplace")'''
assert isinstance(other,Point)
self.x += other.x
self.y += other.y
def is_extreme(self, *points):
for point in points:
if not self > point:
return False
return True
In [22]:
p = Point(5, 6)
p.is_extreme(Point(1,1))
Out[22]:
In [23]:
p.is_extreme(Point(1,1), Point(2,5), Point(6,2))
Out[23]:
We can also use the method via the class instead of the instance, and give the instance of interest (the one that we want to know if it is the extreme) as the first argument self. Much like this, we can either do 'hi'.upper() or str.upper('hi').
In [24]:
Point.is_extreme(Point(7,8), Point(1,1), Point(4,5), Point(2,3))
Out[24]:
In [25]:
class Rectangle1():
"""
Holds a parallel-axes rectangle by storing two points
lower left vertex - llv
upper right vertex - urv
"""
def __init__(self, lower_left_vertex, upper_right_vertex):
assert isinstance(lower_left_vertex, Point)
assert isinstance(upper_right_vertex, Point)
assert lower_left_vertex < upper_right_vertex
self.llv = lower_left_vertex
self.urv = upper_right_vertex
def __repr__(self):
representation = "Rectangle with lower left {0} and upper right {1}"
return representation.format(self.llv, self.urv)
def dimensions(self):
height = self.urv.y - self.llv.y
width = self.urv.x - self.llv.x
return height, width
def area(self):
height, width = self.dimensions()
area = height * width
return area
def transpose(self):
"""
Reflection with regard to the line passing through lower left vertex with angle 315 (-45) degrees
"""
height, width = self.dimensions()
self.urv = self.llv
self.llv = Point(self.urv.x - height, self.urv.y - width)
In [26]:
rec = Rectangle1(Point(), Point(2,1))
print(rec)
print("Area:", rec.area())
print("Dimensions:", rec.dimensions())
rec.transpose()
print("Transposed:", rec)
In [27]:
class Rectangle2():
"""
Holds a parallel-axes rectangle by storing lower left point, height and width
"""
def __init__(self, point, height, width):
assert isinstance(point, Point)
assert isinstance(height, (int,float))
assert isinstance(width, (int,float))
assert height > 0
assert width > 0
self.point = point
self.height = float(height)
self.width = float(width)
def __repr__(self):
representation = "Rectangle with lower left {0} and upper right {1}"
return representation.format(self.point, Point(self.point.x + self.width, self.point.y + self.height))
def dimensions(self):
return self.height, self.width
def area(self):
area = self.height * self.width
return area
def transpose(self):
self.point = Point(self.point.x - self.height , self.point.y - self.width)
self.height, self.width = self.width, self.height
In [29]:
rec = Rectangle2(Point(), 1, 2)
print(rec)
print("Area:", rec.area())
print("Dimensions:", rec.dimensions())
rec.transpose()
print("Transposed:", rec)
In [ ]: