Object-Oriented Programming: Python lists

One of the most important data structures in programming is the List data structure. Programmers use lists everywhere, to solve many different types of problems. In this article, I’ll introduce you to python lists.

This is the second post of a series about Object-Oriented Programming in Python. If you missed the first one, you can find it here.

Two different ways to represent lists. python lists.

What are python lists and why we need them?

A list is a sequence of elements that are in a specific order.

For instance: “a, b, c, d” is a list. The elements are in order, “a” is the first element, “b” is the second one and so on.

Most of the interesting problems in programming, and in real life, deal with a sequence of elements (a list).

Some examples are:

  • Store information of all the cars in a car dealership.
  • Record a list of customers of a business.
  • List the books recommended for a degree in computing.
  • The list of your favourite places, or friends or activities.

There are many examples, that is why it is an important topic to address in programming. Remember programming is about to model what happens in real-life scenarios.

Let’s go back to the problem description of this series. After that, Im going to show you the solution to the new problem using Python lists.

Problem description

Company “AutoCars” has a car rental service. The manager of the company is asking you to create software that helps him to improve the business.

The company keeps a record of all the cars and the customers that at least one time rented a car with them.

For the cars, the business keeps in a record of the year model, make, type of the car (sedan, SUV, 4×4), price per day and if the car uses petrol or diesel.

For the customers, the company keeps the record of the name, id and preferred payment method (cash, ETF, card).

Your task is to design and implement a software in python that helps the manager to keep track of the cars and the customers.

Now the manager asked us to implement the following:

  • Is a certain car available?
  • Is a customer registered already?
  • Assuming that all the cars that are not available are rented, how much money the company will have?

Solutions: Is a certain car available?

Is a certain car available? Let’s see my solution.

class Car:
    def __init__(self, id, year_model, make, type, price_per_day, fuel):
        self._id = id
        self._year_model = year_model
        self._make = make
        self._type = type
        self._price_per_day = price_per_day
        self._fuel = fuel
        self._days_rented = 0

    def is_available(self):
        return self._days_rented == 0

    def how_much_money(self):
        return self._days_rented * self._price_per_day

    def get_id(self):
        return self._id

    def make_it_available(self):
        self._days_rented = 0

I had to add a new attribute (_id) to the class Car because now we need to uniquely identify the cars.  Also, I had to add another attribute to keep track of how many days a car is rented.

The method is available, will return “True” if the days rented equals 0.

To know how much money the company will get, we have to multiply the numbers of days the car is rented times the price per day.

We will need to get the id of the car (get_id) to compare if it is the car we are looking for.

Lastly, the method make_it_available will set up the number of days rented to 0. So when a customer returns the car, it can be available again.

Now the OOP question. Why these methods are implemented in this class?

The previous methods are actions that we can do on the cars. To know if the car is available, to know how much money we get from a car that is rented, to make a car available.

Do you see the pattern?

All the sentences mention the car as the subject of the action. So, we implement the methods on the class Car.

The list of cars

We must ask ourselves now: how can we answer if a certain car is available? The question implies we have to search in the list of cars to know if the specific car is available.

What class have a list of cars? The list of cars is in the class CompanyAutoCars. So in that class is where we have to implement the method that will tell the manager if a car is available.

Let’s check the python code.

class CompanyAutoCars:
    def __init__(self):
        self._customers = []
        self._cars = []

    def add_customer(self, customer):
        self._customers.append(customer)

    def add_car(self, car):
        self._cars.append(car)

    def get_number_of_cars(self):
        return len(self._cars)

    def get_number_of_customers(self):
        return len(self._customers)

    # The python way
    def is_a_car_available(self, car_id):
        return any((car.get_id()==car_id and car.is_available()) for car in self._cars)

    # a better way to understand
    def is_a_car_available_v1(self, car_id):
        for car in self._cars:
            if car.get_id() == car_id:
                return car.is_available()
        return False

Two different implementations with the same result

I added two different implementations. The first one is considered the pythonic way, the “right” way to do it in Python. But that way is difficult to understand for beginners.

I want you to understand this 100% so I used a way that is simpler for you to understand.

Notice the keyword for in the first line. It is a for-loop. Loops are very important in programming and we use them commonly.

Loops are used to repeat a block of instructions several times.

The easy way to understand

Imagine you have 10 cars in front of you. I give you the Vehicle Identification Number (VIN) number (this one is the unique identifier) and I ask you to check whether one of the 10 cars have the VIN I gave you.

What will you do?

If it was me, I will check the VIN of the first car, compare it with the one I have in my hands and if is the same, I’ll say I found it. If it is not the same, I have to do the same the second car, and the third one an so on. The process will finish when I find the car or I check all the cars.

That process of checking the VIN for every car is what we do in the method to find out if the car is available. In our case is not enough to find the car, we also must check if the car is available. For that, we are going to use the method that we implemented in the class car “is_available”.

def is_a_car_available_v1(self, car_id): 
    for car in self._cars:             # I'll repeat the block of code for every car in the list of cars
        if car.get_id() == car_id:     # is this car's VIN number the same that I'm looking for? #If yes, 
                                       # execute the next line. Return the result of calling the method 
                                       # is_available for that specific car. This will stop the execution 
                                       # within the for-loop.  If it is not the car, check the next car on 
                                       #the list.
            return car.is_available()
    return False                       # #If the execution is here, it means the car was not on the list, 
                                       #so we return False.

Remember that in Python we use # to write comments. Everything you write after this symbol won’t be considered as a part of the program, so it won’t be executed.

The console app

See below the new code added to the console app to test if what we added works fine.

car_id = input("Enter the car id you want to know if is available: ")

print(f"Is car {car_id} available: {autocars.is_a_car_available(car_id)}")

print(f"Second way. Is car {car_id} available: {autocars.is_a_car_available_v1(car_id)}")

Notice this code is just we added to the one in the previous post. This code alone is not going to work.

In the first line, we are using the function input. We use this function when we want to enter information from the keyboard. You will see in the screen “Enter the car id you want to know if is available: “ and the execution will stop until you enter the id and press enter in the keyboard. The value you entered will be assigned to the variable car_id.

On the other two lines, we just print the values returned by the new methods we implemented in the class CompanyAutoCars.

Why we only use the new methods from the class CompanyAutoCars if we added also to the class Car?

The answer is easy. In real life, you go to the company and ask someone, you don’t ask the car. In programming is similar, there is always the main class, let’s call it the entry point to the business.

If you go to a University to register for a certain degree, you register at the university, not “at the degree”.

Solution: Is a customer registered?

The solution is similar to the last one. In this one, we check on the list of customers instead of the list of cars. Find bellow my solution.

# The python way
    def is_a_customer_registered(self, customer_id):
        return any(customer.get_id() == customer_id for customer in self._customers)

    # a better way to understand
    def is_a_customer_registered_v1(self, customer_id):
        for customer in self._customers:
            if customer.get_id() == customer_id:
                return True
        return False

The console app

Find bellow the code that you can add to the console application to test if everything works well.

customer_id = input("Enter the customer id: ")

print(f"Is customer {customer_id} registered: {autocars.is_a_customer_registered(customer_id)}")

print(f"Second way. Is customer {customer_id} registered: {autocars.is_a_customer_registered_v1(customer_id)}")

Solutions: Assuming that all the cars that are not available are rented, how much money the company will have?

Let’s see the code and then I’ll explain each step.

def how_much_money_the_company_will_have(self):
        total = 0
        for car in self._cars:
            if not car.is_available():
                total = total + car.how_much_money()
        return total

In this case, we initialise a variable (total) in 0. We do it because we are going to sum several values.

We can read the line ” if not car.is_available()” as if the car is not available. If it is not available, then we add to the total how much money we get from that car. Remember we implemented that method already in the class Car, it just returns the price per day times the number of days the car is rented.

This solution is one of the basic algorithms (also mentioned here). It is called a basic algorithm because we use it commonly.

Let’s see other questions that we can answer using this basic algorithm:

  • Calculate the average marks of a certain student. We first find the total and then divide the number of marks.
  • Calculate the money you need to be financially free.
  • Calculate the total pages of a book, knowing the total pages of each chapter.

The console application

Check the code below.

print(f"The company will make a total of {autocars.how_much_money_the_company_will_have()} ")

car1.rent(10) # someone is renting the car for 10 days.

print(f"The company will make a total of {autocars.how_much_money_the_company_will_have()} ")

Notice that we have to add a new method to the class Car to state that someone is renting the car for a certain number of days.

def rent(self, days):
    self._days_rented = days

Summary

Keys take away:

  • Python lists are awesome! And we have to use them a lot.
  • We need loops to work with lists. Loops are the way that we use lists, without having to repeat the same line of code several times.
  • You must learn the basic algorithms. You will need them a lot in programming.
  • We must implement class methods in the right class, in the class that has the “responsibility” of doing what we want to do. If we want to do something on a car, that must be implemented in a car. If we want to become a customer of a business, that must be implemented in the class that represents the business.
  • In your project, you will always have a main (or several) class. That will be the entry point to your software.
  • If you don’t identify in the right way the class in which you have to implement a certain method, your application won’t work well. The advice is to spend enough time thinking about why the method must be implemented in the class you chose.

Want to try something on your own? I added a few things to the problem you suppose to solve in the previous post.

Homework

The coffee shop “AwesomeCoffee” sell the best coffee in your neighbourhood. The manager of the shop is asking you to create software that helps her to improve the business.

The company keeps a record of the customers that buys coffee.

For the customers the company keeps knows the name and email address.

To satisfy all the customers, the shop sells coffee in several sizes. The shop knows the size of the coffee cup (ml) and the price.

From the above description: Identify and implement the classes. Create a console application that test the new functionalities works well.

These are the new functionalities you can implement now:

  1. Does the shop have a coffee cup of a certain size? Hint: If you have to check the size of all the coffee cups, where is the list of coffee cups?
  2. Does the coffee shop sell coffee at a certain price? Hint: same than the previous one.
  3. How much money the shop will make if it sells one coffee of each size

H@appy coding!!