More examples of classes
Example 1: the Rectangle class
Let's have a look at a class which models a rectangle in two-dimensional space:
class Rectangle:
def __init__(self, left_upper: tuple, right_lower: tuple):
self.left_upper = left_upper
self.right_lower = right_lower
self.width = right_lower[0]-left_upper[0]
self.height = right_lower[1]-left_upper[1]
def area(self):
return self.width * self.height
def perimeter(self):
return self.width * 2 + self.height * 2
def move(self, x_change: int, y_change: int):
corner = self.left_upper
self.left_upper = (corner[0]+x_change, corner[1]+y_change)
corner = self.right_lower
self.right_lower = (corner[0]+x_change, corner[1]+y_change)
A new Rectangle
is created with two tuples as arguments. These tuples contain the x and y coordinates of the upper left corner and the lower right corner. The constructor calculates the height and width of the rectangle based on these values.
The methods area
and perimeter
calculate the area and perimeter of the rectangle based on the height and width. The method move
moves the rectangle by the x and y values given as arguments.
The rectanlge is represented in a coordinate system where the x coordinates increase from left to right, and the y coordinates increase from top to bottom. This is a common way of handling coordinates in programming because it is often easier and more natural to consider the top left corner of the computer screen as the point where x and y equal zero.
The following program tests the Rectangle
class:
rectangle = Rectangle((1, 1), (4, 3))
print(rectangle.left_upper)
print(rectangle.right_lower)
print(rectangle.width)
print(rectangle.height)
print(rectangle.perimeter())
print(rectangle.area())
rectangle.move(3, 3)
print(rectangle.left_upper)
print(rectangle.right_lower)
(1, 1) (4, 3) 3 2 10 6 (4, 4) (7, 6)
Printing an object
When you have an object created from a class defined by yourself, the default reaction to calling the print
command with that object as its argument is not very informative:
rectangle = Rectangle((1, 1), (4, 3))
print(rectangle)
The printout should look a bit like this:
<main.Rectangle object at 0x000002D7BF148A90>
Obviously, we want more control over what is printed out. The easiest way to do this is to add a special __str__
method to the class definition. Its purpose is to return a snapshot of the state of the object in string format. If the class definition contains a __str__
method, the value returned by the method is the one printed out when the print
command is executed.
So, let's add a __str__
method definition to our Rectangle
class:
class Rectangle:
# ...the rest of the class goes here the same as above...
# This method returns the state of the object in string format
def __str__(self):
return f"rectangle {self.left_upper} ... {self.right_lower}"
Now the print
command produces something more user-friendly:
rectangle = Rectangle((1, 1), (4, 3))
print(rectangle)
rectangle (1, 1) ... (4, 3)
The __str__
method is perhaps more often used for formulating a string representation of the object with the str
function, as seen in the following program:
rectangle = Rectangle((1, 1), (4, 3))
str_rep = str(rectangle)
print(str_rep)
rectangle (1, 1) ... (4, 3)
There are many more special underscored methods which can be defined for classes. One rather similar to the __str__
method is the __repr__
method. Its purpose is to provide a technical representation of the state of the object. We will come across this method later.
Example 2: Task list
The following class TaskList
models a list of tasks:
class TaskList:
def __init__(self):
self.tasks = []
def add_task(self, name: str, priority: int):
self.tasks.append((priority, name))
def get_next(self):
self.tasks.sort()
# The list method pop removes and returns the last item in a list
task = self.tasks.pop()
# Return the name of the task (the second item in the tuple)
return task[1]
def number_of_tasks(self):
return len(self.tasks)
def clear_tasks(self):
self.tasks = []
The method add_task
adds a new task to the list. Each task also has a priority attached, which is used for sorting the tasks. The method get_next
removes and returns the task with the highest priority on the list. There is also the number_of_tasks
method, which returns the number of tasks on the list, and finally the method clear_tasks
, which clears the task list.
Within the object, the tasks are stored in a list. Each task is of a tuple containing the priority of the task and its name. The priority value is stored first, so that when the list is sorted, the task with the highest priority is the last item on the list. This is why we can then simply use the pop
method to retrieve and remove the highest priority item.
Please have a look at the following program with the task list in action:
tasks = TaskList()
tasks.add_task("studying", 50)
tasks.add_task("exercise", 60)
tasks.add_task("cleaning", 10)
print(tasks.number_of_tasks())
print(tasks.get_next())
print(tasks.number_of_tasks())
tasks.add_task("date", 100)
print(tasks.number_of_tasks())
print(tasks.get_next())
print(tasks.get_next())
print(tasks.number_of_tasks())
tasks.clear_tasks()
print(tasks.number_of_tasks())
3 exercise 2 3 date studying 1 0
Please respond to a quick questionnaire on this week's materials.
Log in to view the quiz
You can check your current points from the blue blob in the bottom-right corner of the page.