This notebooks contains assingments that are more complex. They are aimed at students who already know about object- oriented Programming from prior experience and who are familiar with the concepts but now how OOP is done on Python.
The scope of this introduction is insufficient to give a good tutorial on OOP as a whole.
Our first example is an example of composition. We create a Company that consists a list of Persons and an account balance.
Then after we structure our classes with desired behaviour we can use them quite freely.
Create a class called Person for storing the following information about a person:
Create a method say_hi that returns the string "Hi, I'm " + the person's name.
In [ ]:
class Person:
def __init__(self, name):
pass
def say_hi(self):
pass
Run the following code to test that you have created the person correctly:
In [ ]:
persons = []
joe = Person("Joe")
jane = Person("Jane")
persons.append(joe)
persons.append(jane)
Now create a class Employee that inherits the class Person. In addition to a name, Employees have a title (string), salary (number) and an account_balance (number).
Override the say_hi method to say "Hi I'm " + name + " and i work as a " + title
In [ ]:
# the reference to Person on the line below means that the object inherits
# Employee
class Employee(Person):
def __init__(self,
name,
salary,
title="Software Specialist",
account_balance=0):
# this calls the constructor of Person class
super().__init__(name)
# you still need to implement the rest
pass
def say_hi(self):
pass
Every employee is also a person.
In [ ]:
persons = []
joe = Person("Joe")
jane = Person("Jane")
persons.append(joe)
persons.append(jane)
emp1 = Employee("Jack", 3000)
emp2 = Employee("Jill", 3000)
persons.append(emp1)
persons.append(emp2)
for person in persons:
print(person.say_hi())
Now create a class called Company, which has a name
and a list of Employee objects called employees and an
account balance for the company.
Make a method payday(self) that will go through
the list of employees and deduct their salary from
the corporate account and add it to the employee
account. Before you start deducting money compute the sum of salaries and make sure it is higher than the account balance. If it is not, raise an instance of the NotEnoughMoneyError.
Make a method layoff(self) that will remove
one employe from the list of employees. If there are no more employees raise a NoMoreEmployeesException.
In [ ]:
class NotEnoughMoneyError(Exception):
pass
class NoMoreEmployeesError(Exception):
pass
class Company(object):
def __init__(self, title, employees = [], account_balance=0):
pass
def payday(self):
pass
def layoff(self):
pass
Okay, you've worked this far just creating the model, let's put it to use.
Make a method smart_payday(company). The method should attempt to call the payday method of the company. If the call raises a NotEnoughMoneyException lay off a worker and then try again. Don't catch the NoMoreEmployeesException as that should be handled at a higher level.
You will probably need to use a while loop to implement the re-trying until a condition is met.
In [ ]:
def smart_payday(company):
pass
In [ ]:
# a bit of test code
names_and_salaries = [
("Jane", 3000),
("Joe", 2000),
("Jill", 2000),
("Jack", 1500)
]
workers = [Employee(name, salary) \
for name, salary in names_and_salaries]
scs = Company("SCS", employees=workers, account_balance=12000)
smart_payday(scs)
print(scs.account_balance)
print(len(scs.employees))
smart_payday(scs)
print(scs.account_balance)
print(len(scs.employees))
print(scs.employees)
Observe how printing the employees list is not very informative? Adding a magic method called __repr__ will help with that.
Consider the following method, it will raise errors randomly. This type of failure is pretty common for IO-related tasks.
In [ ]:
class RandomException(Exception):
pass
def do_wonky_stuff():
import random
if random.random() > 0.5:
raise RandomException("this exception happened randomly")
return
Wrap a call to do_wonky_stuff with a try-except clause.
In [ ]:
do_wonky_stuff()
print("yay it worked")
OK, now let's go even deeper.
In [ ]:
class ReallyRandomException(Exception):
pass
def do_really_wonky_stuff():
import random
val = random.random()
if val > 0.75:
raise RandomException("this exception happened randomly")
elif val < 0.15:
raise ReallyRandomException("This exception is actually quite rare")
return
Wrap do_really_wonky_stuff in a try-except -clause with two excepts. In the rarer of the excepts print out something so you'll if it's your lucky day.
In real life you'd probably want to handle different errors in a different way, or at least log or inform the user of what caused the error.
In [ ]:
do_really_wonky_stuff()