Module-3
Module-3
PYTHON PROGRAMMING
Module-3
(Classes and Exceptions)
OOP Vs POP
• Procedure-oriented Programming(POP) and Object-oriented programming(OOP) both are the
programming approaches, which uses high-level language for programming. A program can be written in
both the languages, but if the task is highly complex, OOP operates well as compared to POP.
• POP approach focuses on procedures or routines (functions) to operate on data. Procedural programming
is often used for tasks that are straightforward and require a clear sequence of steps. It focuses on the
procedure (function) & an algorithm is needed to perform the derived computation.
• OOP is a programming paradigm that organises software design around data, rather than functions and
logic. It is a high-level programming language that divides the program into chunks called objects.
• Python fully supports OOP. This means you can define classes, create objects, and use features like
inheritance, polymorphism, and encapsulation. OOP is used to model real-world entities and relationships,
allowing for code reusability and modular design.
POP Vs OOP
OOP concepts
Python Classes
• Python is an object oriented programming language.
• A class in Python is a blueprint for creating objects. It consists of data (attributes) and functions
(methods) that operate on the data.
• The variables inside a class are called attributes. Attributes are always public and can be
accessed using the dot (.) operator.
• In Python, a class is defined by using the keyword class. Every class has a unique name followed
by a colon ( : ).
• Create a class: To create a class, use the keyword class in Python. The syntax is,
class ClassName:
# class definition
Example:
class Student:
marks=60
Here,
Student - the name of the class and marks - variable inside the class (attribute) with value 60.
Note: Indentation is mandatory for class attributes/functions.
Object:
• In Python, an object is an instance of a class.
• It represents a specific implementation of the blueprint defined by the class.
• Objects are the fundamental building blocks of object-oriented programming in Python,
encapsulating both data (attributes) and behavior (methods).
• Attributes/variables can be accessed using the dot (.) operator.
Syntax: object_name.variable
Create Object:
To create an object (also known as an instance) , we have to use the class name. The
syntax is, object_name=class_name()
Example:
class Student:
marks=60
#Create an object named ob
ob = student()
print(ob.marks)
Example:
class Car:
make = None # or make="Unknown"
year = "Unkown"
#make, and year are class attributes set to None by default. This indicates that these attributes are expected to be defined later.
# Creating an object of the Car class
ob = Car()
# Setting attributes directly
ob.make = "TATA“
ob.year = 2021
# print the attribute values
print("car details:", ob.make, ob.year)
The _ _init_ _() method:
• The _ _init_ _ method allows you to initialize the attributes of the class.
• The _ _init_ _ method in Python is a special method that is automatically called when an instance
of a class (object) is created.
• It is also known as the constructor.
• All classes have a function called _ _init_ _(), which is always executed when the class is being
initiated.
• Syntax for _ _ init_ _() method:
class ClassName:
def _ _init_ _(self, parameters):
self.attribute1 = value1
self.attribute2 = value2
Where,
• def is a keyword.
• _ _init_ _: The name of the method, which is a special name in Python that initializes new objects.
• self: The first parameter of any method in a class, including _ _init_ _, is always self. It refers to the
instance of the class being created. It allows the method to access the attributes and methods of the class.
• parameters: These are additional parameters that you pass to the _ _init_ _ method to initialize the object's
attributes.
self parameter:
In Python, the self parameter is used in instance methods to refer to the instance
of the class on which the method is called. It is a way for the method to access the attributes and
other methods of the specific instance. The following are reasons for using self parameter.
#Create a class named Person, use the _ _init_ _() function to assign values for name and age:
#class
class Person:
def _ _init_ _(self, name, age):
self.name = name
self.age = age
#object
ob = Person(“Sachin", 36) #object with arguments
We can create a method within the class to access the values of the attributes and the function
should be called using the object name of the class outside the class.
Summary
• Classes in Python are a fundamental way to group related data and behavior together.
• Class Definition: Use class to define a class.
• Constructor (_ _init_ _ method): Initialize an object's attributes.
• Attributes: Variables that belong to an object.
• Methods: Functions that belong to an object.
• Instance: An individual object of a class.
• Dot Notation: Access attributes and methods of class using dot notation.
Using classes to group data and behavior is a key concept in object-oriented programming and
can greatly improve the organization and readability of your code.
Python f-string formatting:
Python f-string formatting is a powerful and convenient way to create formatted strings. It allows you to embed
expressions inside string literals, making it easy to interpolate variables and expressions directly into strings.
f”:
This marks the string literal as an f-string, indicating that it will be formatted.
Class Methods
• In Python, class methods are methods that are bound to the class and not the instance of the class.
• They can be called on the class itself, rather than on instances of the class.
• Class methods are defined using the @classmethod decorator just before the method definition.
• The first parameter of a class method is cls, which refers to the class itself.
• In Python, class methods can be accessed without creating an instance of the class. This is
because class methods are bound to the class and not the instance.
• The syntax for a class method is as follows:
class MyClass:
@classmethod
def class_method(cls, arg1, arg2, ...):
# Method body
Class Methods cont…
In the syntax of class method,
@classmethod is a decorator that indicates that the following method is a class
method.
cls is the conventional name for the first parameter of a class method, which
represents the class itself.
arg1, arg2, ….. are the parameters that the class method takes. These parameters
can be any number of arguments just like regular methods, but the first parameter
conventionally represents the class.
Class method example:
Note: If we want to define a method that does not use the self parameter, it should be defined as either a class method or
static method.
Normal Instance Method
The normal instance method should include self as its first parameter, even if it
is not used within the method. Class method
Difference between instance method and class method :
In Python, instance methods and class methods are used to define the
behavior of classes and their instances, but they have different purposes and ways of being called.
First Parameter:
Instance Method: The first parameter is self, which refers to the instance.
Class Method: The first parameter is cls, which refers to the class.
Decorator:
Instance Method: No special decorator is used.
Class Method: The @classmethod decorator is used.
Calling Context:
Instance Method: Called on an instance of the class.
Class Method: Called on the class itself.
…
Exceptions in Python
Exception:
• An exception is an error that occurs during the execution of a program.
• It stops the normal flow of the program and jumps to the exception handling part.
Common Types of Exceptions:
• ZeroDivisionError: Occurs when you try to divide a number by zero.
• TypeError: Occurs when an operation is performed on an inappropriate type.
• ValueError: Occurs when a function receives an argument of the right type but an inappropriate
value.
• IndexError: Occurs when trying to access an element from a list using an index that is out of
range.
• KeyError: Occurs when trying to access a dictionary with a key that doesn't exist.
Exceptions Examples
ZeroDivisionError Example:
we try to calculate the result of dividing 10 by 0. This operation is mathematically
undefined, so Python raises a ZeroDivisionError.
TypeError Example:
we try to add a number and a string together, like 10 + "5". These are different types and
can't be combined in this way, so Python raises a TypeError.
ValueError Example:
We call a function that expects a number, but you pass a string that can't be converted to a
number, like int("hello"). This raises a ValueError.
IndexError Example:
We have a list of three elements, and you try to access the fifth element, like my_list[4].
Since the index is out of range, Python raises an IndexError.
KeyError Example:
We have a dictionary with specific keys, and you try to access a key that doesn't exist, like
my_dict["missing_key"]. Python raises a KeyError.
Why Handle Exceptions?
Handling exceptions is important because it helps you manage
errors gracefully without crashing the program. This makes your programs more robust and
user-friendly.
Try Block:
Contains the code that might raise an exception.
Except Block:
Contains the code that runs if an exception occurs.
Exception Handling
Exception handling in Python is a way to manage errors that occur during the execution of your program. In
Python, the try and except blocks are used to handle exceptions. This allows your program to handle
unexpected events gracefully without crashing.
Basic Components of Exception Handling:
Try Block: This block contains the code that might raise an exception.
Except Block: This block catches and handles the exception if it occurs.
Else Block: This optional block runs if no exceptions were raised in the try block.
Finally Block: This optional block contains code that will always run, regardless of whether an
exception was raised.
try:
Syntax:
# Code that might raise an exception
except ExceptionType:
# Code to handle the exception
else:
# Code to run if no exception occurs (optional)
finally:
# Code to run no matter what (optional)
Exmples for each component of exception handling
try block
try:
# Code that might raise an exception
result = 10 / 0 # This will raise a ZeroDivisionError
Except block
except ZeroDivisionError:
# Code to handle the ZeroDivisionError
print("Error: Cannot divide by zero.")
Else block
else:
# Code to run if no exception occurs
print("The result is:", result)
Finally block
finally:
# Code to run no matter what
print("Execution complete.")
Note: In the try-except block, we can use the `else` after all the `except` statements
finally Keyword in Python (or) Use the finally clause for cleanup actions:
try:
# code that may raise exceptions
except ExceptionType1:
# handle ExceptionType1
except ExceptionType2:
# handle ExceptionType2
....
else:
# code to execute if no exceptions are raised
finally:
# code to execute no matter what (optional)
Example for Handling Multiple Exceptions: We can handle multiple types of exceptions using multiple except blocks.
Using a Single Except Block to Handle Multiple Exceptions
• We can handle multiple types of exceptions in a single except block by specifying a tuple of
exception types.
• The basic syntax for handling multiple exceptions using except block is,
try:
# code that may raise exceptions
except (ExceptionType1, ExceptionType2, ExceptionType3) as e :
# handle any of the specified exceptions
print(e)
else:
# code to execute if no exceptions are raised
Where,
• ExceptionType1, ExceptionType2, … are placeholders for actual exception types (e.g., ValueError, ZeroDivisionError, ..).
• The as e part allows you to access the exception instance/object and its message using the variable e.
Example for Using a Single Except Block to Handle Multiple Exceptions
Python Custom Exception / User-defined Exception
• Sometimes we may need to create our own custom exceptions that serve our purpose.
• In Python, we can define custom exceptions by creating a new class that is derived from the built-in
Exception class.
• To raise the CustomException, we use the raise statement.
• We can create a custom exception by creating a new class that inherits from the built-in Exception
class.
• The syntax to define custom exception is,
class CustomException(Exception):
…
pass
try:
...
except CustomError:
...
Where , CustomError is a user-defined error which inherits from the Exception class.
Example for custom exception/user-define exception:
Division / , % , // operators in Python:
Floating-Point Division (/): Always returns a float.
Modulus (%): Returns the remainder of a division operation.
Integer Division (//): This operator can be used to get the integer quotient of a division, discarding the
fractional part.
Classes as numeric type:
• In Python, you can create custom numeric types by defining classes that implement
special methods for arithmetic operations.
• These special methods, also known as magic methods or dunder methods, allow objects
of your class to behave like built-in numeric types such as integers, floats, or complex
numbers.
• These methods have double underscores before and after their names (hence "dunder"
for double underscore). Here, we'll focus on some common special methods related to
arithmetic operations: __add__, __sub__, __mul__, and __truediv__.
class MyNumber:
def __init__(self, value):
self.value = value
def __add__(self, other):
return MyNumber(self.value + other.value)
# Create instances of MyNumber
num1 = MyNumber(5)
num2 = MyNumber(3)
# Perform arithmetic operation
result_add = num1 + num2
print ("Addition:", result_add)
Memory Allocation:
• Memory allocation is the process of reserving a portion of the computer's memory for use by a
program. When you create variables, objects, or data structures in Python, memory is allocated to
store them.
• Python handles memory allocation automatically. The Python memory manager takes care of this
process.
Object Creation: When you create an object, Python allocates memory for it.
Memory Management: Python manages this memory, making sure it's used efficiently and freed when
no longer needed (garbage collection).
Examples:
(1) Simple variable assignment x=50
Here, Python allocates memory for the integer 50 and then stores the reference to this memory
location in the variable x.
(2) When you create a list, Python allocates memory for the list itself and also for each element in the list.
List=[1 ,2, 3]
Python allocates memory for the list object and then, it allocates memory for each of the integers 1, 2,3.
Garbage Collection:
Garbage collection is a process that automatically cleans up memory that your program doesn't need
anymore, so it can be used for other things.
Reference Counting:
Reference Count: Each object has a count of how many references (or variables) point to it.
Increase Count: When you create a new reference to an object, the count goes up.
Decrease Count: When you delete a reference or it goes away, the count goes down.
Delete Object: When the count goes to zero, the object is deleted
Example:
a = [1, 2, 3] # List's count is 1
b=a # List's count is 2
del a # List's count is 1
del b # List's count is 0, list is deleted
Decorator in Python
Introduction of Decorator :
Consider a simple function that just prints a message.
• This works, but what if you have many functions and you want to add the same extra behavior to all of them?
Writing the extra lines in every function is repetitive and error-prone.
• A decorator allows you to add the extra behavior without modifying the original function. It's like a wrapper that
adds something before and after the original function.
Definition of a Decorator:
• Decorators are one of the most helpful and powerful tools of Python.
• These are used to modify the behavior of the function.
• A decorator is a function that takes another function and extends its behavior without explicitly modifying
it.
• In Decorators, functions are passed as an argument into another function and then called inside the
wrapper function.
The following steps are used while creating a decorate in python.
1. Define the Decorator: A function that takes another function as an argument and returns a new function
(wrapper) that adds extra behavior.
2. Apply the Decorator: Use @decorator_name above the function definition to apply the decorator.
3. Call the Decorated Function: When you call the decorated function, it runs the wrapper function, which
includes the extra behavior and the original function.
Class method example:
Note: If we want to define a method that does not use the self parameter, it should be defined as either a class method or
static method.
Normal Instance Method
The normal instance method should include self as its first parameter, even if it
is not used within the method. Class method
Explanation: In the above program,
my_decorator: This function takes another function (original_func) as an argument.
wrapper: Inside my_decorator, we define another function called wrapper that adds the extra
behavior around original_func.
Prints "Hello".
Calls original_func().
Prints "How are you?".
return wrapper: The wrapper function is returned, which means it will replace original_func.
@my_decorator: This syntax applies the decorator to greeting. It is equivalent to writing
greeting = my_decorator(greeting).
def greeting(): This defines the original greeting function.
After applying the decorator, calling greeting() will actually call the wrapper function inside
my_decorator.
Generators in Python
• In Python, a generator is a function that returns an iterator that produces a sequence of values when
iterated over.
• Generators in Python are a simple way to create iterators.
• Memory Efficiency: Generators do not store the entire sequence in memory.
• They allow you to iterate through a sequence of values without creating the entire sequence in
memory at once.
• Create Python Generator:
In Python, we can create a generator function by simply using the
def keyword, but instead of the return statement we use the yield keyword. The yield keyword
yield values one at a time. The generator has the following syntax in python.
def generator_name():
yield value # More yield statements if needed
Example:
The following example explains how to create and use a generator in Python. In this
example, we will create a simple generator that will yield three integers. Then we will print these
integers by using Python for loop.
“A Practical Introduction to Python Programming”
by
Brain Heinold