0% found this document useful (0 votes)
11 views30 pages

Python Unit2

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)
11 views30 pages

Python Unit2

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
You are on page 1/ 30

Python Material

BCA/BSCIT SEM 5

UNIT 2

OOP using Python


Topic: 1 Handling exceptions
Exception handling in Python is a mechanism used to handle runtime errors (exceptions)
gracefully, preventing the program from crashing abruptly. Instead of the program
halting execution, it allows you to catch the error, handle it, and possibly recover from it
or log it appropriately.

What is an Exception?
An exception is an event that occurs during the execution of a program that disrupts the
normal flow of instructions.

Examples of common exceptions:


ZeroDivisionError – Dividing by zero
ValueError – Passing the wrong value to a function
IndexError – Accessing an invalid list index
KeyError – Accessing a missing key in a dictionary
FileNotFoundError – Trying to open a non-existent file

Syntax of Exception Handling


try:
# Code that might raise an exception
except ExceptionType:
# Code that runs if an exception occurs
else:
# Code that runs if NO exception occurs
finally:
# Code that runs NO MATTER WHAT
Examples:
1. Basic Example

try:
x = 10 / 0
except ZeroDivisionError:
print("You can't divide by zero!")

2. Handling Multiple Exceptions

try:
value = int("abc") # Raises ValueError
except ValueError:
print("Invalid conversion to integer.")
except TypeError:
print("Type mismatch error.")

3. Using else and finally

try:
num = int(input("Enter a number: "))
except ValueError:
print("That's not a valid number.")
else:
print("Number is:", num)
finally:
print("Execution complete.")
4. Catching Multiple Exceptions Together

try:
lst = [1, 2, 3]
print(lst[5]) # IndexError
except (IndexError, ValueError) as e:
print("Caught an error:", e)

5. Custom Exception
You can create your own exception class by extending Exception.

class MyCustomError(Exception):
pass

try:
raise MyCustomError("This is a custom exception")
except MyCustomError as e:
print("Caught custom error:", e)

Task: 1 File Handling

try:
file = open("data.txt", "r")
content = file.read()
print(content)
except FileNotFoundError:
print("File not found. Please check the filename.")
finally:
print("Cleaning up...")
Task: 2 Calculator

try:
a = int(input("Enter first number: "))
b = int(input("Enter second number: "))
result = a / b
except ZeroDivisionError:
print("Error: Cannot divide by zero.")
except ValueError:
print("Error: Please enter valid numbers.")
else:
print("Result is:", result)
finally:
print("Calculation finished.")

Exceptions as a control flow mechanism


Using exceptions as a control flow mechanism means intentionally raising and handling
exceptions to control the logic or flow of execution of a program, rather than using
traditional conditionals like if-else.

Examples of Using Exceptions for Control Flow


Example 1: Dictionary Lookup (Traditional vs Exception)

Traditional approach:
my_dict = {"name": "Anil"}
if "age" in my_dict:
print(my_dict["age"])
else:
print("Age not found")

Exception as control flow:

my_dict = {"name": "Anil"}

try:
print(my_dict["age"])
except KeyError:
print("Age not found")

Example 2: Converting to Integer


Using if:
val = input("Enter number: ")
if val.isdigit():
print(int(val))
else:
print("Invalid number.")

Using exception:
try:
val = int(input("Enter number: "))
print(val)
except ValueError:
print("Invalid number.")
Assertions
Assertions in Python are a debugging aid that test if a condition in your code returns True.
If not, the program will raise an AssertionError with an optional message.
They are mainly used to catch bugs early in development and to ensure that the code
behaves as expected.
An assertion is a statement that asserts or assumes something to be true.

Syntax:
assert condition, optional_message

If the condition evaluates to True, the program continues normally.


If it evaluates to False, the program raises an AssertionError.

Why Use Assertions?


Sanity checks during development.
Validate assumptions about data/state.
Helps catch bugs early.

Example:
def divide(a, b):
assert b != 0, "Denominator cannot be zero"
return a / b

print(divide(10, 2))
print(divide(10, 0)) #AssertionError
Abstract Data Types (ADTs)
An Abstract Data Type (ADT) is a logical description of how data is organized and what
operations can be performed on it — without focusing on how it is implemented.
An ADT defines what a data structure does, not how it does it.

Characteristics of ADTs
Encapsulation: The internal representation is hidden.
Defined operations: Only specific operations are allowed.
Implementation-independent: Can be implemented in various ways.

Examples of ADTs in Python:


ADT Description Real-world analogy
Stack LIFO (Last-In-First-Out) Plates on a stack
Queue FIFO (First-In-First-Out) People in line
List Indexed collection Shopping list
Map (Dict) Key-value pairs Phonebook
Set Unordered unique elements Unique student roll numbers

Example: Stack ADT


Stack ADT Operations:
push(item)
pop()
peek()
is_empty()
size()
Code:

class Stack:
def __init__(self):
self.items = []

def push(self, value):


self.items.append(value)

def pop(self):
assert not self.is_empty(), "Stack is empty"
return self.items.pop()

def peek(self):
assert not self.is_empty(), "Stack is empty"
return self.items[-1]

def is_empty(self):
return len(self.items) == 0

def size(self):
return len(self.items)

# Usage
s = Stack()
s.push(5)
s.push(10)
print(s.pop())
print(s.peek())
Classes in Python
A class is a blueprint for creating objects (instances). It allows you to model real-world
entities with properties (data) and behaviors (methods).
It defines the attributes (data/variables) and methods (functions) that the object will
have.
Think of a class as a recipe, and objects as the cakes baked from that recipe.

Why Use Classes?


Encapsulation: Bundle data & methods together.
Abstraction: Hide implementation details.
Reusability: Write once, use multiple times.
Inheritance: Extend existing classes.

Class Syntax:
class ClassName:
def __init__(self, attributes):
self.attribute = attributes

def method(self):
pass

Object
An object is an instance of a class.
Once a class is defined, you can create multiple objects from it, each having its own set of
attributes.
Example: Person Class

class Person:
def __init__(self, name, age):
self.name = name
self.age = age

def speak(self):
return f"My name is {self.name} and I am {self.age} years old."

p1 = Person("Kapil", 30)
print(p1.speak())

Important Concepts

__init__() Constructor
Special method that is called when a new object is created.
Used to initialize object attributes.

def __init__(self, name):


self.name = name

self Keyword
Refers to the current object instance.
It must be the first parameter of methods in class.

self.name = name
Special Methods: __str__, @property

class Rectangle:
def __init__(self, length, width):
self.length = length
self.width = width

@property
def area(self):
return self.length * self.width
def __str__(self):
return f"Rectangle({self.length} x {self.width})"

r = Rectangle(10, 5)
print(r.area)
print(r)

Inheritance
Inheritance is a core concept of Object-Oriented Programming (OOP) that allows one
class (called child or derived class) to inherit the properties and methods of another class
(called parent or base class).

Why Use Inheritance?

 Code Reusability: Avoid rewriting common code.


 Extendibility: Add or override functionality.
 Polymorphism: Common interface for different classes.
Syntax of Inheritance in Python

class Parent:

# parent class code

class Child(Parent):

# child class code (inherits from Parent)

Types of Inheritance in Python

Type Description

Single Inheritance One child class inherits from one parent

Multiple Inheritance One child inherits from multiple parents

Multilevel Inheritance Child inherits from a parent, which itself inherits

Hierarchical Inheritance Multiple children inherit from one parent

Hybrid Inheritance Combination of two or more types above

1. Single Inheritance

A child class inherits from one parent class.

Diagram:

Parent

Child

Example (Single Inheritance)

class Person:

def __init__(self, name, age):

self.name = name
self.age = age

def show(self):

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

class Student(Person): # Inherits from Person

def __init__(self, name, age, student_id):

super().__init__(name, age) # Call parent constructor

self.student_id = student_id

def show_student(self):

self.show()

print(f"Student ID: {self.student_id}")

s1 = Student("Ravi", 20, "ST101")

s1.show_student()

2. Multilevel Inheritance

A class is derived from a class that is already derived from another class.

Diagram:

Grandparent

Parent

Child
Example (Multilevel Inheritance)

class Animal:

def sound(self):

print("Animal makes a sound")

class Dog(Animal):

def sound(self):

print("Dog barks")

class Lion(Dog):

def sound(self):

print("Lion Roars")

l = Lion()

l.sound()

3. Multiple Inheritance

A child class inherits from more than one parent class.

Diagram:

Parent1 Parent2

\ /

Child
Example (Multiple Inheritance)

class Father:

def skills(self):

print("Gardening, Carpentry")

class Mother:

def skills(self):

print("Cooking, Art")

class Child(Father, Mother):

def skills(self):

Father.skills(self)

Mother.skills(self)

print("Python Programming")

c = Child()

c.skills()

4. Hierarchical Inheritance

Multiple child classes inherit from a single parent class.

Diagram:

Parent

/ \

Child1 Child2
Example (Hierarchical Inheritance)

class Vehicle:

def start(self):

print("Vehicle starting...")

class Car(Vehicle):

def drive(self):

print("Driving a car")

class Bike(Vehicle):

def ride(self):

print("Riding a bike")

car = Car()

car.start()

car.drive()

bike = Bike()

bike.start()

bike.ride()
5. Hybrid Inheritance

A combination of two or more types of inheritance.

Diagram:

/\

B C

\/

Example (Hybrid Inheritance)

class A:

def a(self):

print("A")

class B(A):

def b(self):

print("B")

class C(A):

def c(self):

print("C")

class D(B, C):

def d(self):
print("D")

obj = D()

obj.a()

obj.b()

obj.c()

obj.d()

Task: Employee Management System

Create classes for Employee, Manager, and Developer using inheritance.

class Employee:

def __init__(self, name, salary):

self.name = name

self.salary = salary

def show(self):

print(f"Name: {self.name}, Salary: {self.salary}")

class Manager(Employee):

def __init__(self, name, salary, team_size):

super().__init__(name, salary)

self.team_size = team_size
def show(self):

super().show()

print(f"Team Size: {self.team_size}")

class Developer(Employee):

def __init__(self, name, salary, language):

super().__init__(name, salary)

self.language = language

def show(self):

super().show()

print(f"Language: {self.language}")

m = Manager("Ravi", 90000, 10)

d = Developer("Anu", 70000, "Python")

m.show()

print("-----")

d.show()

super() in Inheritance

Used to call methods from the parent class.

class A:

def show(self):
print("A class method")

class B(A):

def show(self):

super().show()

print("B class method")

B().show()

Encapsulation and information hiding


Encapsulation is an Object-Oriented Programming (OOP) concept where the data
(attributes) and the code (methods) operating on the data are bundled together into a single
unit, i.e., a class.
It helps to protect data from unauthorized access and allows controlled access through
methods.

Information Hiding means restricting access to the internal state of an object and exposing
only what is necessary.

It supports the concept of abstraction and security, making sure implementation details are
hidden from the user.

Benefits of Encapsulation & Information Hiding

 Protects object integrity by preventing unauthorized access/modification


 Increases security
 Improves maintainability and readability
 Enables modularity and abstraction
Example 1: Encapsulation using Class

class Employee:
def __init__(self, name, salary):
self.name = name # public
self.__salary = salary # private

def show(self):
print(f"Name: {self.name}, Salary: {self.__salary}")

def increase_salary(self, amount):


if amount > 0:
self.__salary += amount

emp = Employee("Raj", 50000)


emp.show()
emp.increase_salary(5000)
emp.show()

# Direct access to __salary (won’t work)


# print(emp.__salary) AttributeError

Example 2: Protected Members

class Person:
def __init__(self, name, age):
self._name = name # Protected
self._age = age
def show(self):
print(f"{self._name} is {self._age} years old")

class Student(Person):
def display(self):
print(f"Student name is {self._name}")

s = Student("Ravi", 20)
s.show()
s.display()

Protected members are accessible in subclasses but should not be accessed from outside
directly (by convention). But in python there is no concept of protected member.

Example 3: Getter and Setter Methods


Encapsulation is best practiced using getter and setter methods for private attributes.

class BankAccount:
def __init__(self, balance):
self.__balance = balance

def get_balance(self):
return self.__balance

def set_balance(self, amount):


if amount >= 0:
self.__balance = amount
else:
print("Invalid amount!")
account = BankAccount(10000)
print("Balance:", account.get_balance())
account.set_balance(12000)
print("Updated Balance:", account.get_balance())

Search Algorithms
A search algorithm is a method to find a specific item (like a number or a record) in a
collection such as a list, array, or tree.
It returns either the location (index) of the item or indicates that the item is not present.

Types of Search Algorithms


Type Description
Linear Search Check each element one by one
Binary Search Repeatedly divide sorted array in half

1. Linear Search

Scan elements one by one.


Works on unsorted or sorted data.
Simple, but slow for large datasets.

Example:

def linear_search(arr, target):


for i in range(len(arr)):
if arr[i] == target:
return i # Return index
return -1 # Not found

data = [5, 3, 8, 6, 7]
print(linear_search(data, 6))

2. Binary Search
Works on sorted data only.
Repeatedly divides the search interval in half.
Much faster than linear for large data.

Example:

def binary_search(arr, target):


left = 0
right = len(arr) - 1

while left <= right:


mid = (left + right) // 2

if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1

data = [1, 3, 5, 7, 9, 11]


print(binary_search(data, 7))
Sorting Algorithms

A sorting algorithm is a method used to rearrange elements in a list or array into a specific
order — usually in ascending or descending order.

In Python, sorting algorithms help organize data (like numbers, strings, or objects) for
easier searching, analysis, or presentation.

Why is Sorting Important?

 Improves search speed (binary search needs sorted data)


 Organizes output (like ranking or reports)
 Prepares data for algorithms like searching, merging, etc.

Types of Sorting Orders

1. Ascending Order → [1, 3, 5, 8]


2. Descending Order → [8, 5, 3, 1]

Example: Built-in Sorting in Python

data = [5, 2, 9, 1, 7]

# Ascending sort
data.sort()
print(data) # Output: [1, 2, 5, 7, 9]

# Descending sort
data.sort(reverse=True)
print(data) # Output: [9, 7, 5, 2, 1]

Or use sorted() (returns a new list):

data = [3, 1, 4, 2]
sorted_data = sorted(data)
print(sorted_data) # [1, 2, 3, 4]

Common Sorting Algorithms

1. Bubble Sort

Logic:
Compare each pair of adjacent items.
Swap if they are in the wrong order.
Repeat until the list is sorted.

Example:

def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1): # Last i elements are already in place
if arr[j] > arr[j + 1]: # Swap if the element found is greater
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr

print(bubble_sort([64, 25, 12, 22, 11]))

2. Selection Sort
Logic:
Find the minimum element in the unsorted part.
Swap it with the first unsorted element.

Example:
def selection_sort(arr):
for i in range(len(arr)):
min_idx = i
for j in range(i + 1, len(arr)):
if arr[j] < arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]
return arr
print(selection_sort([64, 25, 12, 22, 11]))
3. Insertion Sort
Logic:
Build the sorted array one element at a time.
Insert each item into its correct position.

Example:
def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j=i-1
while j >= 0 and key < arr[j]: # Move elements that are greater
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
return arr
print(insertion_sort([64, 25, 12, 22, 11]))

Hashtable
A hashtable (or hash map) is a data structure that stores key-value pairs. It uses a hash
function to compute an index (called a hash code) into an array of buckets, from which the
desired value can be found.
In Python, dictionaries (dict) are the built-in implementation of hashtables.

Features of Hashtable (Python dict)


Key-based access to values.
Keys must be unique.
Values can be any type.
Example of a Hashtable (using dict)

# Creating a hashtable (dictionary)


student = {
"name": "Ravi",
"age": 21,
"course": "Python"
}

# Accessing values
print(student["name"]) # Output: Ravi

# Adding a new key-value pair


student["email"] = "[email protected]"

# Updating a value
student["age"] = 22

# Removing a key
del student["course"]

# Checking if key exists


if "email" in student:
print("Email is", student["email"])

# Iterating through keys and values


for key, value in student.items():
print(key, ":", value)
Common Dictionary (Hashtable) Operations
Operation Syntax Description
Create d = {} Empty hashtable
Add/Update d[key] = value Add or update key-value pair
Access d[key] Get value for a key
Remove del d[key] Delete a key
Keys/Values/Items d.keys(), d.values() Return all keys, values, or key-value pairs
Iterate for k, v in d.items(): Loop through key-value pairs

Example: Word Counter


def word_counter(text):
words = text.lower().split()
count = {}

for word in words:


if word in count:
count[word] += 1
else:
count[word] = 1

return count

text = "Python is fast and Python is easy"


print(word_counter(text))

You might also like