0% found this document useful (0 votes)
3 views14 pages

OOP Python Notes Optimized

The document provides an overview of Object-Oriented Programming (OOP) principles, including classes, objects, encapsulation, inheritance, polymorphism, and modules in Python. It explains how OOP organizes code using real-world analogies, such as cars and students, and demonstrates these concepts with code examples. Additionally, it covers the creation and use of custom modules and packages in Python.

Uploaded by

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

OOP Python Notes Optimized

The document provides an overview of Object-Oriented Programming (OOP) principles, including classes, objects, encapsulation, inheritance, polymorphism, and modules in Python. It explains how OOP organizes code using real-world analogies, such as cars and students, and demonstrates these concepts with code examples. Additionally, it covers the creation and use of custom modules and packages in Python.

Uploaded by

dgurukanth
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Module 4- Object-Oriented Programming & Modules

What is Object-Oriented Programming?


Before OOP existed, programs were written as a long sequence of instructions — like a recipe.
Everything was scattered. Data lived separately from the functions that used it. As programs grew
bigger, managing them became a nightmare.
OOP was born to solve this: organize code the way the real world is organized.
The Real World Analogy — A Car
Look at a car. Every car has:
Properties (what it has):
• Brand, color, fuel level, speed
Behaviors (what it does):
• Start, accelerate, brake, stop
Now imagine a car factory. The factory does not build one car — it has a blueprint (design template).
Using that one blueprint, it manufactures thousands of cars. Each car is independent — one car
running low on fuel does not affect another.
In OOP:
Real World Python OOP
Blueprint / Design Class
Actual Car built from blueprint Object / Instance
Color, Speed, Fuel Attributes (variables)
Start, Brake, Accelerate Methods (functions)

Now Feel It in Python


▶ Code:
class Car: # Blueprint
def __init__(self, brand, color):
[Link] = brand # Attribute
[Link] = color
[Link] = 0

def accelerate(self): # Behavior


[Link] += 20
print(f"{[Link]} accelerates! Speed:
{[Link]} km/h")

def brake(self):
[Link] -= 10
print(f"{[Link]} brakes! Speed: {[Link]}
km/h")
1
# Two cars built from the SAME blueprint
car1 = Car("Toyota", "Red")
car2 = Car("BMW", "Black")

[Link]()
[Link]()
[Link]()
[Link]()
Output:
Toyota accelerates! Speed: 20 km/h
Toyota accelerates! Speed: 40 km/h
Toyota brakes! Speed: 30 km/h
BMW accelerates! Speed: 20 km/h

Notice — car1 and car2 are completely independent. Each has its own speed. One blueprint,
multiple real objects. That is the heart of OOP.
The 4 Pillars of OOP
OOP stands on 4 pillars. Here is the intuition using our Car:
Pillar Simple Meaning Car Example
Encapsulation Bundle data + behavior Fuel system hidden; you just
together, hide internals press accelerator
Inheritance Child class gets parent's ElectricCar inherits Car, adds
features + adds its own charge_battery()
Polymorphism Same action, different behavior brake() works differently in
SportsCar vs Truck
Abstraction Show only what's necessary, You press brake — hydraulics
hide complexity hidden inside

1. Classes and Objects


A class is a blueprint or template. An object is a real instance created from that blueprint. Think of a
class as the architect's plan and an object as the actual building constructed from it.
Syntax:
class ClassName:
def __init__(self, parameters):
[Link] = value

2
object_name = ClassName(arguments)

Example 1 — Student Class


▶ Code:
class Student:
def __init__(self, name, marks):
[Link] = name
[Link] = marks

def display(self):
print(f"Student: {[Link]}, Marks: {[Link]}")

def grade(self):
if [Link] >= 90:
return "A"
elif [Link] >= 75:
return "B"
else:
return "C"

stu1 = Student("Manjunath", 92)


stu2 = Student("Ravi", 78)

[Link]()
print(f"Grade: {[Link]()}")
[Link]()
print(f"Grade: {[Link]()}")
Output:
Student: Manjunath, Marks: 92
Grade: A
Student: Ravi, Marks: 78
Grade: B

Example 2 — Bank Account Class


▶ Code:
class BankAccount:
def __init__(self, owner, balance=0):
[Link] = owner
[Link] = balance

3
def deposit(self, amount):
[Link] += amount
print(f"Deposited {amount}. Balance:
{[Link]}")

def withdraw(self, amount):


if amount <= [Link]:
[Link] -= amount
print(f"Withdrawn {amount}. Balance:
{[Link]}")
else:
print("Insufficient funds!")

acc = BankAccount("Manjunath", 1000)


[Link](500)
[Link](200)
[Link](2000)
Output:
Deposited 500. Balance: 1500
Withdrawn 200. Balance: 1300
Insufficient funds!

2. Instance and Class Variables


Instance variables: Belong to a specific object. Each object has its own copy. Defined inside __init__
using self.
Class variables: Shared across all objects of the class. Defined outside __init__ directly inside the
class.
Example 1 — School with Class Variable
▶ Code:
class School:
school_name = "Vidyaniketan" # Class variable (shared)

def __init__(self, student_name, grade):


self.student_name = student_name # Instance
variable
[Link] = grade

def display(self):
print(f"School: {School.school_name} | Student:
{self.student_name} | Grade: {[Link]}")

4
s1 = School("Manjunath", "A")
s2 = School("Priya", "B")

[Link]()
[Link]()

# Changing class variable


School.school_name = "National Public School"
[Link]() # Reflects new name for ALL objects
Output:
School: Vidyaniketan | Student: Manjunath | Grade: A
School: Vidyaniketan | Student: Priya | Grade: B
School: National Public School | Student: Manjunath | Grade: A

Example 2 — Employee Counter


▶ Code:
class Employee:
count = 0 # Class variable — tracks total employees

def __init__(self, name, dept):


[Link] = name # Instance variable
[Link] = dept
[Link] += 1 # Increment shared counter

def show(self):
print(f"Employee: {[Link]} | Dept: {[Link]}")

e1 = Employee("Manjunath", "Analytics")
e2 = Employee("Kavya", "HR")
e3 = Employee("Rahul", "Finance")

[Link]()
[Link]()
print(f"Total Employees: {[Link]}")
Output:
Employee: Manjunath | Dept: Analytics
Employee: Kavya | Dept: HR
Total Employees: 3

5
3. Encapsulation
Encapsulation means bundling data (attributes) and methods (behaviors) together inside a class,
and restricting direct access to internal data from outside the class.
Access Modifiers in Python:
• Public — [Link] (accessible anywhere)
• Protected — self._name (accessible within class & subclasses, by convention)
• Private — self.__name (name-mangled, not directly accessible outside)
Example 1 — Private Attribute with Getter/Setter
▶ Code:
class Person:
def __init__(self, name, age):
[Link] = name
self.__age = age # Private attribute

def get_age(self): # Getter


return self.__age

def set_age(self, age): # Setter with validation


if age > 0:
self.__age = age
else:
print("Invalid age!")

p = Person("Manjunath", 35)
print(f"Name: {[Link]}")
print(f"Age: {p.get_age()}")

p.set_age(36)
print(f"Updated Age: {p.get_age()}")

p.set_age(-5) # Invalid
Output:
Name: Manjunath
Age: 35
Updated Age: 36
Invalid age!

6
Example 2 — ATM Machine (Real World Encapsulation)
▶ Code:
class ATM:
def __init__(self, pin, balance):
self.__pin = pin # Private
self.__balance = balance # Private

def check_balance(self, pin):


if pin == self.__pin:
print(f"Balance: Rs. {self.__balance}")
else:
print("Wrong PIN!")

def withdraw(self, pin, amount):


if pin != self.__pin:
print("Wrong PIN!")
elif amount > self.__balance:
print("Insufficient balance!")
else:
self.__balance -= amount
print(f"Withdrawn: Rs. {amount}. Remaining: Rs.
{self.__balance}")

atm = ATM(1234, 10000)


atm.check_balance(1234)
[Link](1234, 3000)
[Link](9999, 1000) # Wrong PIN
Output:
Balance: Rs. 10000
Withdrawn: Rs. 3000. Remaining: Rs. 7000
Wrong PIN!

4. Inheritance
Inheritance allows a child class (subclass) to acquire the properties and methods of a parent class
(superclass). This promotes code reuse — write once, use everywhere.
Types:
• Single Inheritance: One child inherits from one parent
• Multiple Inheritance: One child inherits from multiple parents
Single Inheritance — Example 1
▶ Code:

7
class Animal: # Parent class
def __init__(self, name):
[Link] = name

def speak(self):
print(f"{[Link]} makes a sound.")

class Dog(Animal): # Child class


def speak(self): # Overriding parent method
print(f"{[Link]} says: Woof!")

class Cat(Animal):
def speak(self):
print(f"{[Link]} says: Meow!")

a = Animal("Generic Animal")
[Link]()

d = Dog("Bruno")
[Link]()

c = Cat("Whiskers")
[Link]()
Output:
Generic Animal makes a sound.
Bruno says: Woof!
Whiskers says: Meow!

Multiple Inheritance — Example 2


▶ Code:
class Father:
def skills(self):
print("Father: Engineering, Driving")

class Mother:
def skills(self):
print("Mother: Cooking, Teaching")

class Child(Father, Mother): # Inherits from both


def skills(self):
8
[Link](self)
[Link](self)
print("Child: Python, Power BI")

c = Child()
[Link]()
Output:
Father: Engineering, Driving
Mother: Cooking, Teaching
Child: Python, Power BI

5. Polymorphism
Polymorphism means "many forms." The same method name behaves differently based on the
object calling it. There are two main types:
• Method Overriding: Child class provides its own version of a parent method
• Method Overloading: Same method name with different behaviors (Python achieves this via
default arguments)
Method Overriding — Example 1
▶ Code:
class Shape:
def area(self):
print("Area not defined")

class Circle(Shape):
def __init__(self, radius):
[Link] = radius

def area(self):
print(f"Circle Area: {3.14 * [Link] ** 2}")

class Rectangle(Shape):
def __init__(self, l, w):
self.l = l
self.w = w

def area(self):
print(f"Rectangle Area: {self.l * self.w}")

shapes = [Circle(7), Rectangle(5, 10), Shape()]


for s in shapes:
9
[Link]() # Same call, different behavior
Output:
Circle Area: 153.86
Rectangle Area: 50
Area not defined

Method Overloading via Default Arguments — Example 2


▶ Code:
class Calculator:
def add(self, a, b, c=0): # c is optional
return a + b + c

def multiply(self, a, b=1): # b is optional


return a * b

calc = Calculator()

print([Link](5, 10)) # Two numbers


print([Link](5, 10, 15)) # Three numbers
print([Link](6)) # One number
print([Link](6, 7)) # Two numbers

Output:
15
30
6
42

6. Working with Modules and Packages


A module is a Python file (.py) containing functions, classes, and variables. A package is a folder
containing multiple modules with an __init__.py file.
Python provides many built-in modules. Three of the most commonly used ones are math, random,
and datetime.
6.1 The math Module
▶ Code:
import math

print("Square root of 144:", [Link](144))


print("Value of pi:", [Link])
print("Power 2^10:", [Link](2, 10))
print("Floor of 4.7:", [Link](4.7))
10
print("Ceil of 4.2:", [Link](4.2))
print("Factorial of 5:", [Link](5))
Output:
Square root of 144: 12.0
Value of pi: 3.141592653589793
Power 2^10: 1024.0
Floor of 4.7: 4
Ceil of 4.2: 5
Factorial of 5: 120

6.2 The random Module


▶ Code:
import random

print([Link](1, 100)) # Random integer 1-100


print([Link]()) # Random float 0.0-1.0

fruits = ["Apple", "Mango", "Banana", "Grapes"]


print([Link](fruits)) # Pick one randomly

numbers = [10, 20, 30, 40, 50]


[Link](numbers) # Shuffle in place
print(numbers)

print([Link](range(1,50), 6)) # Lottery: 6 unique


numbers
Output (sample — values change each run):
73
0.6823451287634
Mango
[30, 10, 50, 20, 40]
[12, 34, 7, 45, 23, 18]

6.3 The datetime Module


▶ Code:
from datetime import datetime, date, timedelta

now = [Link]()
print("Current datetime:", now)
print("Year:", [Link])
print("Month:", [Link])
11
print("Day:", [Link])

today = [Link]()
print("Today:", today)

future = today + timedelta(days=30)


print("30 days from today:", future)

bday = date(1990, 6, 15)


age = today - bday
print(f"Days since birthday: {[Link]}")
Output (sample):
Current datetime: 2026-05-14 09:35:22.456123
Year: 2026
Month: 5
Day: 14
Today: 2026-05-14
30 days from today: 2026-06-13
Days since birthday: 13118

7. Creating Custom Modules and Packages


You can create your own module simply by saving Python code in a .py file and importing it into
another file.
Example 1 — Creating and Importing a Custom Module
Step 1: Create a file called [Link]
▶ [Link]:
# [Link] — Custom module

def add(a, b):


return a + b

def subtract(a, b):


return a - b

def square(n):
return n * n

PI = 3.14159

12
Step 2: Import and use it in [Link]
▶ [Link]:
import mymath

print([Link](10, 5))
print([Link](10, 5))
print([Link](6))
print([Link])

Output:
15
5
36
3.14159

Example 2 — Creating a Package


A package is a folder with multiple module files and an __init__.py file.
Folder structure:
mypackage/
__init__.py # Makes it a package
[Link]
[Link]
▶ [Link]:
def hello(name):
return f"Hello, {name}! Welcome to Python."

▶ [Link]:
def multiply(a, b):
return a * b

▶ Using the package in [Link]:


from mypackage import greet, calculate

print([Link]("Manjunath"))
print([Link](6, 7))

Output:
Hello, Manjunath! Welcome to Python.
42

13
Quick Reference Summary
Concept Key Idea Example
Class & Object Blueprint and instance Car class, car1 object
Instance Variable Belongs to one object [Link] = 0
Class Variable Shared by all objects [Link] = 0
Encapsulation Hide private data self.__balance
Inheritance Child gets parent features class Dog(Animal)
Polymorphism Same method, diff behavior area() in Circle vs Rectangle
Module Python file with reusable code import math
Package Folder of modules from mypackage import greet

14

You might also like