0% found this document useful (0 votes)
4 views

Object Oriented Programming

Object Oriented Programming (OOP) in Python allows developers to create modular and scalable applications using classes and objects. Key concepts include encapsulation, inheritance, access specifiers, and the use of constructors and destructors to manage object lifecycle. The document also provides examples of classes, objects, and their methods, illustrating how to implement OOP principles effectively.

Uploaded by

Kanza Fatima
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Object Oriented Programming

Object Oriented Programming (OOP) in Python allows developers to create modular and scalable applications using classes and objects. Key concepts include encapsulation, inheritance, access specifiers, and the use of constructors and destructors to manage object lifecycle. The document also provides examples of classes, objects, and their methods, illustrating how to implement OOP principles effectively.

Uploaded by

Kanza Fatima
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 48

Object Oriented

Programming
Introduction
• Object Oriented Programming is a fundamental
concept in Python, empowering developers to build
modular, maintainable, and scalable applications.
• OOPs is a way of organizing code that uses objects and
classes to represent real-world entities and their
behavior.
Python Class
A class is considered a blueprint of objects.

We can think of the class as a sketch


(prototype) of a house. It contains all the
details about the floors, doors, windows, etc.

Based on these descriptions, we build the


house; the house is the object.

Since many houses can be made from the same


description, we can create many objects from a
class.
Python Objects

• An object is called an instance of


a class.

• Suppose Bike is a class then we


can create objects like bike1,
bike2, etc from the class.
Explanation:
1. We define a class named Dog using the class keyword.
2. 2. The __init__ method is a special method that's called
when an object is created. It initializes the object's
attributes, name and age.
3. The bark method is a simple method that prints "Woof!".
4. We create an object named my_dog by calling the Dog class
with the arguments "Max" and 3.
5. We access the object's attributes using dot notation (e.g.,
my_dog.name).
6. We call the object's method using dot notation (e.g.,
my_dog.bark()).
class Person:
def __init__(self, name):
self.name = name

def greet(self):
print(f"Hello, my name is {self.name}.") In this example:-
We define a Person class with an attribute (name) and a
# Create an object of the Person method (greet).-
classjohn = Person("John") We create an object john of the Person class.-
We call the greet method on the john object.
# Call the greet method
john.greet()
class Book: Explanation:
def __init__(self, title, author): 1. We define a class named Book with one attribute: title.
self.title = title 2. The __init__ method initializes the object's title attribute.
self.author = author 3. The display_title method prints the book's title.
4. We create an object named my_book by calling the Book
def display_info(self): class with the argument "To Kill a Mockingbird"
print(f"Title: {self.title}") 5. We call the object's display_title method to print the
print(f"Author: {self.author}") book's title.

# Create an object of the Book class


book1 = Book("To Kill a Mockingbird", "Harper Lee")

# Call the display_info method Output:


book1.display_info() Title: To Kill a Mockingbird
Author: Harper Lee
Access Specifiers, Data Members, and Member Functions
These are keywords (public, private, protected) that determine how
members of a class can be accessed.

public: Members declared as public are accessible from anywhere


within the program, including outside the class.

private: Members declared as private are only accessible within the


class itself (by its member functions and friend functions) and are not
directly accessible from outside the class.

protected: Members declared as protected are accessible within the


class itself and by derived (sub)classes.
class Car {
public:
void startEngine() { /* anyone can start the engine */ }
void accelerate() { /* anyone can accelerate */ }
private:
double fuelLevel; // only Car methods can access
void refillFuel() { /* only Car methods can refill fuel */ }
protected:
void changeGear() { /* Car methods and derived classes
(e.g., SportsCar) can access */ }};
class SportsCar : public Car {
public: void boostSpeed() {
changeGear(); // SportsCar can access protected
method // ...
}
};
Data Members
Data members are variables that are declared inside a
class. They are used to store data.
Data members can be public, private, or protected.
Example:
class Student:
def __init__(self, name, age):
self.public_name = name # public data member
self.__private_age = age # private data member
def display_details(self):
print(f"Name: {self.public_name}")
print(f"Age: {self.__private_age}")
Member Functions
Member functions are functions that are declared inside a class.
They are used to perform operations on data members. Member
functions can be public, private, or protected.
Example:
class Student:
def __init__(self, name, age):
self.public_name = name
self.__private_age = age

def display_details(self): # public member function


print(f"Name: {self.public_name}")
print(f"Age: {self.__private_age}")

def __calculate_grade(self):
# private member function
# calculate grade based on age pass
Accessing Data Members and Member
Functions
Data members and member functions can be accessed using the
dot notation
Example:
student = Student("John Doe", 20)
print(student.public_name) # accessing public data member
student.display_details() # accessing public member function
Benefits of Access Specifiers
Access specifiers provide several benefits,
including:
1. Encapsulation: Access specifiers help to hide
internal implementation details from the
outside world.
2. Data Hiding: Access specifiers prevent
unauthorized access to data members.
3. Code Reusability: Access specifiers enable
code reusability by allowing derived classes
to access protected members.
What are Constructors?
• A constructor is a special method that is called when an
object is created. Its purpose is to initialize the object's
attributes and set up the object's state.
• Think of a constructor like building a house. When you build
a house, you need to lay the foundation, install the
plumbing and electrical systems, and finish the interior.
• A constructor does the same thing for an object: it sets up
the object's foundation and gets it ready for use.
What are Destructors?
• A destructor is a special method that is called when an object is
destroyed. Its purpose is to release any system resources held by
the object and perform cleanup tasks.
• Think of a destructor like demolishing a house. When you
demolish a house, you need to tear down the structure,
disconnect the utilities, and haul away the debris.
• A destructor does the same thing for an object: it cleans up after
the object and releases any resources it was using.
Example: Student Class
Let's consider an example.
Suppose we have a Student class with attributes for the
student's name and age.
We can define a constructor that initializes these
attributes:
class Student:
def __init__(self, name, age):
self.name = name
self.age = age

def display_details(self):
print(f"Name: {self.name}, Age: {self.age}")

In this example, the __init__ method is the constructor. It


takes two parameters, name and age, and uses them to
initialize the object's attributes.
Example:
File Handler Class
Let's consider another example.
Suppose we have a File Handler class that opens a file and
provides methods for reading and writing to the file. We can
define a constructor that opens the file and a destructor that
closes the file:
class FileHandler:
def __init__(self, filename):
self.filename = filename
self.file = open(filename, "w")

def write_to_file(self, content):


self.file.write(content)

def __del__(self):
self.file.close()
print(f"File {self.filename} closed.")

In this example, the __init__ method is the constructor, and the


__del__ method is the destructor.
The constructor opens the file, and the destructor closes the
file.
Information hiding and encapsulation
• are two fundamental concepts in object-oriented programming
(OOP).
• Information hiding refers to the idea of hiding the implementation
details of an object from the outside world.
• Encapsulation is the concept of bundling data and methods that
operate on that data within a single unit.
• Think of a car.
• You don't need to know how the engine works to drive the car.
• You only need to know how to interact with the car through its
interface (e.g., steering wheel, pedals).
• This is an example of information hiding and encapsulation.
Information Hiding
• Information hiding is a design principle that suggests hiding
internal implementation details from the outside world.
• This means that an object's internal state and behavior
should be invisible to other objects.
Why Information Hiding?
Information hiding provides several benefits, including:
1. Improved Modularity: Information hiding promotes modularity by
allowing objects to be designed and implemented independently.
2. Reduced Coupling: Information hiding reduces coupling between
objects by minimizing dependencies.
3. Increased Flexibility: Information hiding makes it easier to change
internal implementation details without affecting other objects.
Encapsulation
Encapsulation is a mechanism that enforces
information hiding. It involves bundling data
and methods that operate on that data within a
single unit, called a class or object.

Encapsulation in Python
In Python, encapsulation is achieved
using classes and objects. A class defines
the structure and behavior of an object,
while an object is an instance of a class.
In this example,
the Bank Account class encapsulates the
account_number and balance data
members, making them inaccessible
from outside the class. The deposit and
get_balance methods provide controlled
access to the encapsulated data.
Access Modifiers
Python provides access modifiers to control access to encapsulated
data.
The three access modifiers are:
1. Public: No underscore prefix. Accessible from anywhere.
2. Private: Double underscore prefix (e.g., __balance). Inaccessible
from outside the class.
3. Protected: Single underscore prefix (e.g., _balance). Accessible
within the class and its subclasses.

Benefits of Encapsulation
Encapsulation provides several benefits, including:
4. Improved Code Organization: Encapsulation promotes code
organization by bundling related data and methods.
5. Increased Data Integrity: Encapsulation ensures data integrity by
controlling access to data.
6. Reduced Code Duplication: Encapsulation reduces code
duplication by providing a single interface to access data.
Thinking time
Here's a project idea that applies the basics of OOP in Python:
Project: Bank Account Management System
Create a Bank Account Management System using Python classes and objects. The system should allow users to:
1. Create a new bank account
2. Deposit money into an account
3. Withdraw money from an account
4. Check account balance
5. Display account details

Requirements:
1. Define a BankAccount class with the following attributes:
- account_number (private)
- account_holder (private)
- balance (private)
2. Implement the following methods:
- __init__ (constructor) to initialize account attributes
- deposit to add money to the account
- withdraw to subtract money from the account
- get_balance to return the account balance
- get_account_details to return account details (account number, account holder, balance)
3. Use access specifiers (public, private, protected) to encapsulate data members and member functions.
4. Implement information hiding and encapsulation principles.
5. Create a Bank class that manages a list of BankAccount objects.
Reference variables
• .
In programming, a reference variable is a variable that stores the
memory address of an object.
When you assign an object to a variable, you are actually creating a
reference to that object.
Think of a map.
A map is a reference to a physical location.
If you have multiple maps that point to the same location,
changing the location on one map will affect all the other maps.
Using Reference Variables in Python
In Python, reference variables are used to store the memory address of an object.
When you assign an object to a variable, you are actually creating a reference to that
object.
Here's how you can use reference variables in Python:
Creating Reference Variables
You can create a reference variable by assigning an object to a variable.
For example:
# Create a list object
my_list = [1, 2, 3]
# Create a reference variable
ref_list = my_list
print(ref_list)
# Output: [1, 2, 3]
In this example, ref_list is a reference variable that points to the same list object as
my_list.
Modifying the Referenced Object

When you modify the referenced object through a reference variable, the changes are reflected
in the original object.
For example:
# Create a list object
my_list = [1, 2, 3]
# Create a reference variable
ref_list = my_list
# Modify the referenced object through the reference variable
ref_list.append(4)
print(my_list)
# Output: [1, 2, 3, 4]
In this example, the append method is called on the referenced object through the ref_list
reference variable.
The changes are reflected in the original my_list object
Reassigning Reference Variables
When you reassign a reference variable, it no longer points to the original object.
For example:
# Create a list object
my_list = [1, 2, 3]
# Create a reference variable
ref_list = my_list
# Reassign the reference variable
ref_list = [4, 5, 6]
print(my_list)
# Output: [1, 2, 3]
print(ref_list)
# Output: [4, 5, 6]
In this example, the ref_list reference variable is reassigned to point to a new list object.
The original my_list object remains unchanged.
Copying Objects
To create a copy of an object, you can use the copy() method or the deepcopy() function from
the copy module.
For example:
import copy
# Create a list object
my_list = [1, 2, 3]
# Create a copy of the object
ref_list = copy.copy(my_list)
# Modify the copied object
ref_list.append(4)
print(my_list)
# Output: [1, 2, 3]
print(ref_list)
# Output: [1, 2, 3, 4]
In this example, the copy.copy() method is used to create a shallow copy of the my_list object.
The ref_list reference variable points to the copied object, and modifying the copied object does
Inheritance in Python
Inheritance is a fundamental concept in OOP that allows one class to
inherit the properties and behavior of another class.

Think of a family tree. A child inherits traits and characteristics from


their parents. In programming, a child class can inherit the
properties and behavior of a parent class
# Parent class
class Vehicle:
def __init__(self, brand, model, year):
self.brand = brand
self.model = model
self.year = year
self.mileage = 0
def drive(self, miles):
self.mileage += miles
def describe_vehicle(self):
print(f"This vehicle is a {self.year} {self.brand} {self.model} with {self.mileage} miles.")

# Child class
class Car(Vehicle):
def __init__(self, brand, model, year, doors):
super().__init__(brand, model, year)
self.doors = doors

def lock_doors(self):
print("The doors are now locked.")
def describe_vehicle(self):

super().describe_vehicle()
print(f"It has {self.doors} doors.")
# Child class
class Truck(Vehicle):
def __init__(self, brand, model, year, bed_size):
super().__init__(brand, model, year)
self.bed_size = bed_size
def lower_bed(self):
print("The bed is now lowered.")
def describe_vehicle(self):
super().describe_vehicle()
print(f"It has a {self.bed_size} bed.")
# Create instances of the child classes
my_car = Car("Toyota", "Corolla", 2015, 4)
my_truck = Truck("Ford", "F-150", 2010, "6.5 ft")
# Call methods on theinstances
my_car.drive(100)
my_car.lock_doors()
my_car.describe_vehicle()
print()my_truck.drive(50)
my_truck.lower_bed()
my_truck.describe_vehicle()
In this example:-
The Vehicle class is the parent class, which has attributes for brand, model,
year, and mileage, as well as methods for driving the vehicle and describing it.
- The Car and Truck classes are child classes that inherit from the Vehicle
class.
- They have additional attributes and methods specific to cars and trucks,
respectively.-
- The super() function is used to call the parent class's methods from the child
classes.-
- Instances of the Car and Truck classes are created, and their methods are
called to demonstrate inheritance.
Types of Inheritance
Python supports several types of inheritance:-
Single Inheritance: A child class inherits from a single parent
class.
Multiple Inheritance: A child class inherits from multiple
parent classes.
Multilevel Inheritance: A child class inherits from a parent
class, which in turn inherits from another parent class.
Hierarchical Inheritance: A parent class has multiple child
classes.
Method Overriding
Method overriding is a feature of inheritance where a child class provides a different implementation of a method
that is already defined in its parent class.

Think of a restaurant. A restaurant may have a standard recipe for a dish, but a chef may choose to override
that recipe with their own implementation

Here's an example of method overriding:


# Parent class
class Shape:
def area(self):
pass
# Child class
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
# Create an instance of the child class
my_circle = Circle(5)
# Call the area method
print(my_circle.area())
# Output: 78.5
In this example, the Circle class overrides the area method of the Shape class.
Method Overloading
Method overloading is a feature of some programming languages
where multiple methods with the same name can be defined,
but with different parameter lists.
Python does not support method overloading in the classical sense,
but it can be achieved using optional parameters or the *args and
**kwargs syntax.
Abstract Classes and Methods
Abstract classes and methods are used to define a blueprint for other
classes to follow.
An abstract class cannot be instantiated, and it must be subclassed by
a concrete class.
Here's an example of an abstract class and method:from abc
import ABC, abstractmethod
# Abstract class
class AbstractShape(ABC):
@abstractmethod
def area(self):
pass
# Concrete class
class Circle(AbstractShape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
# Create an instance of the concrete class
my_circle = Circle(5)
# Call the area method
print(my_circle.area())
# Output: 78.5
In this example, the AbstractShape class defines an abstract
method area, which is implemented by the Circle class
Operator Overloading
Operator overloading is a feature in Python that allows
developers to redefine the behavior of operators such as +, -, *,
/, etc. when working with user-defined objects.

Magic Methods
Magic methods, also known as dunder methods (short for
"double underscore"), are special methods in Python classes
that are automatically called when certain operators are used.
These methods are surrounded by double underscores (__) on
either side of the method name.
Some common magic methods include:-
__init__: Initializes the object-
__str__: Returns a string representation of the object-
__repr__: Returns a string representation of the object
that can be used to recreate it-
__add__: Defines the behavior of the + operator
__sub__: Defines the behavior of the - operator
__mul__: Defines the behavior of the * operator
__truediv__: Defines the behavior of the / operator
Operator Overloading
Operator overloading is a concept in programming where operators such as +, -, *, /, etc. are
redefined for user-defined objects.
Think of a simple example of adding two numbers:
2+3=5
Now, imagine you have two objects, "Apple" and "Banana", and you want to "add" them together.
What does it mean to "add" two fruits?
In operator overloading, you can redefine the + operator to mean combining the two fruits into
new fruit salad.
Magic Methods
Magic methods are special methods in programming that are automatically called when certain
operators are used.
Think of a simple example of creating a new object:
Imagine you have a class for "Book" and you want to create a new book object.
You can define a magic method to initialize the book object with a title and author.
Magic methods are like shortcuts that allow you to perform complex operations with simple
syntax.
Example
Imagine you have a toy box where you can add and remove toys.
You can define magic methods to make it easy to add and remove toys
from the box.
For example, you can define a magic method called "add_toy" that allows
you to add a new toy to the box.
You can also define a magic method called "remove_toy" that allows you
to remove a toy from the box.
With these magic methods, you can easily manage your toy box without
having to write complex code.

Operator overloading and magic methods have several benefits:-


They make code easier to read and write-
They allow for more flexibility and customization-
They can simplify complex operations-
They can improve code reusability
Real-World Applications
• Game development: Magic methods can be used to create game
objects and operator overloading can be used to define game logic.-
• Scientific computing: Operator overloading can be used to define
mathematical operations on complex data structures.-
• Data analysis: Magic methods can be used to create data objects
and operator overloading can be used to define data analysis
operations.
Example
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"Vector({self.x}, {self.y})"
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar) In this example,
# Create two vectors the Vector class defines magic methods for addition,
v1 = Vector(2, 3) subtraction, and multiplication.
v2 = Vector(4, 5) These methods allow us to overload the +, -, and * operators to
# Add two vectors work with Vector objects
v3 = v1 + v2
print(v3) # Output: Vector(6, 8)
# Subtract two vectors
v4 = v1 - v2
print(v4) # Output: Vector(-2, -2)# Multiply a vector by a
scalarv5 = v1 * 2print(v5) # Output: Vector(4, 6).
Example
class Fruit:
def __init__(self, name):
self.name = name
def __add__(self, other):
return FruitSalad(self.name, other.name)
class FruitSalad:
def __init__(self, fruit1, fruit2):
self.fruit1 = fruit1
self.fruit2 = fruit2
def __str__(self):
return f"{self.fruit1} and {self.fruit2} salad“
apple = Fruit("Apple")
banana = Fruit("Banana")
fruit_salad = apple + banana
print(fruit_salad) # Output: Apple and Banana salad
In this example, the Fruit class defines an __add__ magic method to overload the + operator and
create a new FruitSalad object.
The FruitSalad class defines an __init__ magic method to initialize the object and an __str__
magic method to return a string representation of the object.
Polymorphism
is the ability of an object to take on multiple forms, depending on
the context in which it is used.
This allows objects of different classes to be treated as objects of a
common superclass.
Types of Polymorphism:
There are several types of polymorphism:
1. Method Overloading: When multiple methods with the same
name can be defined, but with different parameter lists.
2. Method Overriding: When a subclass provides a specific
implementation for a method that is already defined in its
superclass.
3. Operator Overloading: When operators such as +, -, *, /, etc. are
redefined for a class.
4. Function Polymorphism: When multiple functions with the same
name can be defined, but with different parameter lists
Benefits:
Polymorphism provides several benefits, including:
1. Increased flexibility: Polymorphism allows objects of different
classes to be treated as objects of a common superclass.
2. Easier maintenance: Polymorphism makes it easier to modify or
extend existing code without affecting other parts of the program.
3. Improved code reuse: Polymorphism enables code reuse by
allowing objects of different classes to be treated as objects of a
common superclass.
class Animal:
def sound(self):
print("The animal makes a sound")
In this example:- We define a base class
class Dog(Animal):
Animal with a method sound().- We create
def sound(self):
two subclasses Dog and Cat that inherit
print("The dog barks")
from Animal and override the sound()
class Cat(Animal):
method.- We define a function
def sound(self):
make_sound() that takes an Animal object
print("The cat meows")
as an argument and calls its sound()
def make_sound(animal: Animal):
method.- We create instances of Dog, Cat,
animal.sound()
and Animal and pass them to the
dog = Dog()
make_sound() function.This demonstrates
cat = Cat()
polymorphism because the make_sound()
animal = Animal()
function can work with objects of different
make_sound(dog) # Output: The dog barks
classes (Dog, Cat, and Animal) without
make_sound(cat) # Output: The cat meows
knowing their specific class type.
make_sound(animal) # Output: The animal makes a sound

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy