Lecture One
Lecture One
History of OOP
Object-Oriented Programming (OOP) originated in the 1960s to solve the complexity of large-scale software
development. The first programming language that fully embraced OOP concepts was Simula (developed in
Page 1 of 22
1967 by Ole-Johan Dahl and Kristen Nygaard). They introduced the idea of objects to model real-world entities
more intuitively.
Later, Smalltalk (developed in the 1970s by Alan Kay and his team) became one of the most influential OOP
languages, inspiring the development of modern OOP languages such as C++, Java, and Python.
Benefits of OOP
1. Modularity : Code is divided into objects, making it easier to manage and understand. If you need to
make a change, you can do so in one part of the system without affecting others.
2. Code Reusability : Through inheritance, you can create new objects that share the properties and
behaviors of existing ones, reducing duplication.
3. Flexibility and Scalability : OOP allows for easier updates and improvements to software systems. You
can add new features by creating new objects without rewriting existing code.
4. Encapsulation : Objects hide their internal state from the outside world and only expose certain
functions (methods), improving security and protecting data.
5. Abstraction : You can focus on higher-level designs without worrying about the complex details inside
each object.
6. Polymorphism : OOP allows one function to work in different ways depending on the object it is acting
on. For example, a method to draw a shape can behave differently when applied to a circle or a square.
3. Encapsulation : Bundling of data and methods that operate on the data within one unit (class) and
restricting access to some of the object's components.
4. Inheritance : A mechanism by which one class (child class) can inherit properties and behaviors from
another class (parent class), promoting code reuse.
Page 3 of 22
5. Polymorphism : The ability of different objects to respond to the same method call in different ways.
Page 4 of 22
Feature Object-Oriented Programming (OOP) Procedural Programming
Structure Based on objects and classes. Based on functions and procedures.
Data Handling Data and functions are encapsulated in Data is separate from functions, and
objects. passed between them.
Reusability Inheritance and polymorphism allow for Functions can be reused, but not as
code reuse. flexibly as in OOP.
Ease of Easier to maintain due to modular structure Harder to maintain as the program grows
Maintenance (classes). larger.
Abstraction Provides abstraction through objects, hiding Less abstraction; focus is on step-by-step
details. execution.
Real-World Excellent for modeling complex, real-world Less suited for complex, real-world
Modeling systems. modeling.
Example Creating a Car class and objects for each Writing separate functions for each part
car. of a car’s behavior.
Scalability More scalable for larger applications with Less scalable as complexity increases.
complex interactions.
Object :
An object is an instance of a class. It represents individual entities that have state (attributes) and behavior
(methods). Each object created from the same class will have unique values for its attributes but share the same
structure and behavior.
Example of Objects:
Page 6 of 22
Let’s say we create two Person objects, Jessa and Jon .
Jessa :
Name: Jessa
Sex: Female
Profession: Software Engineer
Behavior: Working as a software developer, studying 2 hours a day.
Jon :
Name: Jon
Sex: Male
Profession: Doctor
Behavior: Working as a doctor, studying 5 hours a day.
Both Jessa and Jon are objects created from the same Person class, but they have different states
(attributes) and behaviors (methods).
class ClassName:
def __init__(self, attribute1, attribute2):
self.attribute1 = attribute1
self.attribute2 = attribute2
def method1(self):
# method implementation
def method2(self):
# method implementation
Components:
Page 7 of 22
class ClassName : Defines a new class.
__init__(self, attribute1, attribute2) : A special method called a constructor, which initializes
the object's attributes.
self.attribute1 = attribute1 : Assigns the value of the attribute to the object.
Methods: Functions defined within a class to represent behaviors.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
Creating an Object:
Constructors in Python
What is a Constructor?
A special method within a class that is automatically called when an object of that class is created.
Its purpose is to initialize the object's attributes (instance variables) and perform any necessary setup.
In Python, the constructor method is named __init__() .
Page 8 of 22
Object Creation and Initialization
Object creation involves allocating memory for the object.
Object initialization sets its initial state.
The __new__() method (which we don't explicitly define) handles memory allocation and returns the
newly created object.
The __init__() method initializes the object by setting its attributes.
Syntax of a Constructor
To create a constructor in Python, define a method named __init__() within your class.
The first parameter of __init__() is typically self , which refers to the current instance (object).
Inside the constructor, you can set initial values for the object's attributes.
def __init__(self):
# body of the constructor
Page 9 of 22
It refers to the current object that the method is working with.
Think of it as a way for the object to talk about itself.
Talking to Ourselves
Imagine the book saying, "Hey, I'm 'The Great Gatsby' by F. Scott Fitzgerald!"
self lets the book say that about itself.
Page 10 of 22
+--------------------+
| Musician |
+--------------------+
| - name: str |
| - instrument: str |
| - band: str |
+--------------------+
| + play_instrument(): str |
| + introduce(): str |
+--------------------+
Class Definition:
class Musician:
def __init__(self, name, instrument, band):
self.name = name
self.instrument = instrument
self.band = band
def play_instrument(self):
return f"{self.name} is playing the {self.instrument}."
def introduce(self):
return f"{self.name} is a member of {self.band} and plays the {self.instrument}."
Creating Objects:
print(musician1.play_instrument())
print(musician2.introduce())
2. Car Class
+--------------------+
| Car |
+--------------------+
| - make: str |
| - model: str |
| - year: int |
+--------------------+
| + start(): str |
| + stop(): str |
| + honk(): str |
+--------------------+
Class Definition:
Page 11 of 22
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def start(self):
return f"The {self.year} {self.make} {self.model} is starting."
def stop(self):
return f"The {self.year} {self.make} {self.model} is stopping."
def honk(self):
return "Honk! Honk!"
Creating Objects:
print(car1.start())
print(car2.honk())
class Person:
def __init__(self, name, sex, profession):
# Data members (instance variables)
self.name = name
self.sex = sex
self.profession = profession
Explanation:
__init__ method : This is a constructor method in Python, automatically called when you create a new
object. It initializes the attributes of the object.
Instance Variables : self.name , self.sex , self.profession represent the state of an object.
Instance Methods : show() and work() define the behavior of the object.
Page 12 of 22
Creating Objects of a Class
Now, let’s create objects from the Person class.
# Creating objects
person1 = Person("Fatu", "Female", "Software Engineer")
person2 = Person("Hassan", "Male", "Doctor")
# Accessing methods
person1.show()
person1.work()
person2.show()
person2.work()
Output:
Name: Fatu, Sex: Female, Profession: Software Engineer
Fatu is working as a Software Engineer
Name: Hassan, Sex: Male, Profession: Doctor
Hassan is working as a Doctor
Here, person1 and person2 are two different objects of the Person class, each with its own values for name ,
sex , and profession .
Attributes in Classes
Understanding Attributes
Attributes are like the characteristics or properties of an object. They define what an object is and what it can
do. There are two main types:
1. Instance Attributes:
Belong to individual objects.
Defined within the __init__ method.
Accessed using self.attribute_name .
2. Class Attributes:
Shared by all instances of a class.
Defined directly within the class.
Accessed using ClassName.attribute_name or self.attribute_name .
Page 13 of 22
Example: The Employee Class
Let's use an Employee class to illustrate these concepts:
class Employee:
# Class attribute
company_name = "Limkokwing University"
In this example:
company_name is a class attribute . It's shared by all employees in the company.
name and salary are instance attributes . Each employee has their own unique name and salary.
Accessing Attributes
Instance attributes:
Page 14 of 22
employee1.name # Accessing the name of employee1
employee2.salary # Accessing the salary of employee2
Class attributes:
Page 15 of 22
class Employee:
company_name = "Limkokwing University"
# Instance method
def get_salary(self):
return f"{self.name} earns {self.salary}"
# Class method
@classmethod
def company_info(cls):
return f"Company: {cls.company_name}"
Using Methods
Instance methods:
employee1.get_salary() # Output: "Omar Leigh earns 50000"
Class methods:
Requirements:
1. Attributes :
Class attribute:
school : A class attribute to store the name of the school that all students belong to.
Instance attributes:
name : The name of the student.
age : The age of the student.
student_id : A unique ID for each student.
subject : The subject the student is majoring in.
grades : The grade the student has received for different assessments (e.g., exam,
project).
2. Methods :
__init__(self, name, age, student_id, subject, exam_grade, project_grade) : A
constructor to initialize the student's attributes.
display_info(self) : A method to display the student's name, age, student ID, subject, and
grades.
calculate_average(self) : A method to calculate and display the student's average grade.
update_grade(self, exam_grade=None, project_grade=None) : A method to update the
student's exam or project grade.
Page 17 of 22
# Define the Student class
class Student:
# Class attribute (common to all students)
school = "Green Valley High School"
Explanation:
Page 18 of 22
1. Class and Instance Attributes:
The class attribute school is shared across all student objects, meaning every student belongs to the
same school.
Instance attributes ( name , age , student_id , subject , exam_grade , and project_grade ) are
unique for each student and are initialized through the __init__ constructor.
2. Methods:
display_info() : This method prints out the personal and academic details of a student.
calculate_average() : This method calculates the average of the exam and project grades and
displays it.
update_grade() : This method updates a student’s grades for either the exam, the project, or both. If
you provide a value for exam_grade , it will update that specific grade. If you provide a value for
project_grade , it updates that. If no new values are provided, the grades remain unchanged.
Class Attributes:
1. company_name (string) - The name of the company.
2. total_employees (integer) - A counter to keep track of the total number of employees.
Instance Attributes:
1. name (string) - The employee's name.
2. employee_id (integer) - A unique identifier for the employee.
3. department (string) - The department where the employee works.
4. salary (float) - The employee's salary.
5. hire_date (datetime object) - The date the employee was hired.
6. is_active (boolean) - Indicates whether the employee is currently active.
7. position (string) - The employee's job title.
8. email (string) - The employee's email address.
9. hourly_rate (float) - The employee's hourly wage.
Page 19 of 22
10. university (string) - The name of the university the employee attended.
Instance Methods:
1. get_employee_info() - Returns a string containing the employee's name, ID, department, salary, hire
date, position, email, university, and whether they are active.
2. calculate_annual_salary() - Calculates the employee's annual salary based on their hourly rate and
a standard 40-hour work week.
3. get_years_of_service() - Calculates the number of years the employee has been with the company.
4. terminate_employment() - Sets the is_active attribute to False .
5. update_email(new_email) - Updates the employee's email address.
6. promote(new_position, salary_increase) - Updates the employee's position and increases their
salary by the specified amount.
7. is_eligible_for_retirement() - Returns True if the employee has been with the company for 20
years or more, otherwise False .
8. update_university(new_university) - Updates the employee's university name.
Class Methods:
1. get_company_name() - Returns the name of the company.
2. get_total_employees() - Returns the total number of employees.
Challenge:
Implement the Employee class with the above attributes and methods. Ensure that the class methods and
instance methods work correctly and that the class attributes are properly managed. Test your implementation
with various employee instances to verify that all functionalities are working as expected.
Class Attributes:
1. dealership_name (string) - The name of the dealership.
2. total_cars (integer) - A counter to keep track of the total number of cars in the dealership.
Instance Attributes:
1. make (string) - The manufacturer of the car.
2. model (string) - The model of the car.
Page 20 of 22
3. year (integer) - The year the car was manufactured.
4. vin (string) - The Vehicle Identification Number of the car.
5. price (float) - The price of the car.
6. is_sold (boolean) - Indicates whether the car is sold.
7. mileage (integer) - The mileage of the car.
8. color (string) - The color of the car.
Instance Methods:
1. get_car_info() - Returns a string containing the car's make, model, year, VIN, price, mileage, color,
and whether it is sold.
2. sell_car() - Sets the is_sold attribute to True .
3. update_price(new_price) - Updates the car's price.
4. is_available() - Returns True if the car is not sold, otherwise False .
5. update_mileage(new_mileage) - Updates the car's mileage.
Class Methods:
1. get_dealership_name() - Returns the name of the dealership.
2. get_total_cars() - Returns the total number of cars in the dealership.
Challenge:
Implement the Car class with the above attributes and methods. Ensure that the class methods and instance
methods work correctly and that the class attributes are properly managed. Test your implementation with
various car instances to verify that all functionalities are working as expected.
Class Attributes:
1. bank_name (string) - The name of the bank.
2. total_accounts (integer) - A counter to keep track of the total number of bank accounts.
Instance Attributes:
1. account_holder (string) - The name of the account holder.
2. account_number (string) - The unique account number.
Page 21 of 22
3. balance (float) - The current balance of the account.
4. account_type (string) - The type of the account (e.g., savings, checking).
5. is_active (boolean) - Indicates whether the account is active.
6. interest_rate (float) - The interest rate applicable to the account.
Instance Methods:
1. get_account_info() - Returns a string containing the account holder's name, account number,
balance, account type, and whether it is active.
2. deposit(amount) - Adds the specified amount to the account balance.
3. withdraw(amount) - Subtracts the specified amount from the account balance if sufficient funds are
available.
4. calculate_interest() - Calculates the interest earned based on the current balance and interest rate.
5. close_account() - Sets the is_active attribute to False .
Class Methods:
1. get_bank_name() - Returns the name of the bank.
2. get_total_accounts() - Returns the total number of bank accounts.
Challenge:
Implement the BankAccount class with the above attributes and methods. Ensure that the class methods and
instance methods work correctly and that the class attributes are properly managed. Test your implementation
with various account instances to verify that all functionalities are working as expected.
Page 22 of 22