Python OOPs Concepts
An object-oriented paradigm is to design the program using classes and objects.
The object is related to real-word entities such as book, house, pencil, etc.
The oops concept focuses on writing the reusable code.
It is a widespread technique to solve the problem by creating objects.
Major principles of object-oriented programming system are given below:
o Class
o Object
o Method
o Inheritance
o Polymorphism
o Data Abstraction
o Encapsulation
Class
The class can be defined as a collection of objects. It is a logical entity that has some specific
attributes and methods. For example: if you have an employee class, then it should contain an
attribute and method, i.e. an email id, name, age, salary, etc.
Syntax
class ClassName:
<statement-1>
.
.
<statement-N>
Define a Class
All class definitions start with the class keyword, which is followed by the name of the
class and a colon. Any code that is indented below the class definition is considered part
of the class’s body.
Here’s an example of a Dog class:
class Dog:
pass
The body of the Dog class consists of a single statement: the pass keyword.
pass is often used as a placeholder indicating where code will eventually go.
It allows you to run this code without Python throwing an error.
Note: Python class names are written in CapitalizedWords notation by convention. For
example, a class for a specific breed of dog like the Jack Russell Terrier would be written
as JackRussellTerrier.
There are a number of properties that we can choose from, including name, age, coat
color, and breed. To keep things simple, we’ll just use name and age.
The properties that all Dog objects must have are defined in a method called
.__init__()
What is __init__ in Python?
In Python, __init__ is a special method known as the constructor. It is
automatically called when a new instance (object) of a class is created.
The __init__ method allows you to initialize the attributes (variables) of an object.
How Does __init__() Method Work?
The python __init__ method is declared within a class and is used to initialize the
attributes of an object as soon as the object is formed. While giving the definition
for an __init__(self) method, a default parameter, named ‘self’ is always passed
in its argument.
This self represents the object of the class itself. Like in any other method of a
class, in case of __init__ also ‘self’ is used as a dummy object variable for
assigning values to the data members of an object.
The __init__ method is often referred to as double underscores init or dunder init
for it has two underscores on each side of its name. These double underscores on
both the sides of init imply that the method is invoked and used internally in
Python, without being required to be called explicitly by the object.
Init in Python: Syntax and Examples
We can declare a __init__ method inside a class in Python using the following
syntax:
class class_name():
def __init__(self):
# Required initialisation for data members
# Class methods
…
…
Example:
class MyClass:
def __init__(self, name, age):
[Link] = name
[Link] = age
def display_info(self):
print(f"Name: {[Link]}")
print(f"Age: {[Link]}")
# Creating an instance of MyClass
obj = MyClass("John", 25)
# Accessing attributes and calling methods
obj.display_info()
F-string is a way to format strings in Python. It was introduced in Python to make it
easier for users to add variables, comma separators, do padding with zeros and date
format.
Object
The object is an entity that has state and behavior. It may be any real-world object like the
mouse, keyboard, chair, table, pen, etc.
Everything in Python is an object, and almost everything has attributes and methods. All
functions have a built-in attribute __doc__, which returns the docstring defined in the function
source code.
When we define a class, it needs to create an object to allocate the memory.
Method
The method is a function that is associated with an object. In Python, a method is not unique
to class instances. Any object type can have methods.
Inheritance
Inheritance is the most important aspect of object-oriented programming, which simulates the
real-world concept of inheritance.
It specifies that the child object acquires all the properties and behaviours of the parent
object.
By using inheritance, we can create a class which uses all the properties and behavior of another
class. The new class is known as a derived class or child class, and the one whose properties
are acquired is known as a base class or parent class.
It provides the re-usability of the code.
Benefits of inheritance are:
Inheritance allows you to inherit the properties of a class, i.e., base class to another, i.e., derived
class. The benefits of Inheritance in Python are as follows:
• It represents real-world relationships well.
• It provides the reusability of a code. We don’t have to write the same code again and
again. Also, it allows us to add more features to a class without modifying it.
• It is transitive in nature, which means that if class B inherits from another class A, then
all the subclasses of B would automatically inherit from class A.
• Inheritance offers a simple, understandable model structure.
• Less development and maintenance expenses result from an inheritance.
Syntax
• Class BaseClass:
• {Body}
• Class DerivedClass(BaseClass):
• {Body}
Tpyes of Inheritance
Based on number of ways inheriting the feature of base class into derived class we
have five types of inheritance; they are:
• Single inheritance
• Multiple inheritance
• Hierarchical inheritance
• Multilevel inheritance
Single inheritance
In python, a derived class can inherit base class by just mentioning the base in the bracket
after the derived class name. Consider the following syntax to inherit a base class into the
derived class.
Syntax
1. class derived-class(base class):
2. <class-suite>
Example:
# Python program to demonstrate single inheritance
# Base class
class Parent:
def func1(self):
print("This function is in parent class.")
# Derived class
class Child(Parent):
def func2(self):
print("This function is in child class.")
# Driver's code
object = Child()
object.func1()
object.func2()
Output:
This function is in parent class.
This function is in child class.
Multiple Inheritance:
When a class can be derived from more than one base class this type of inheritance is
called multiple inheritances. In multiple inheritances, all the features of the base classes
are inherited into the derived class.
Example:
# Python program to demonstrate multiple inheritance
# Base class1
class Mother:
mothername = ""
def mother(self):
print([Link])
# Base class2
class Father:
fathername = ""
def father(self):
print([Link])
# Derived class
class Son(Mother, Father):
def parents(self):
print("Father :", [Link])
print("Mother :", [Link])
# Driver's code
s1 = Son()
[Link] = "RAM"
[Link] = "SITA"
[Link]()
Output:
Father : RAM
Mother : SITA
Multilevel Inheritance :
In multilevel inheritance, features of the base class and the derived class are further
inherited into the new derived class. This is similar to a relationship representing a child
and a grandfather.
Syntax
class class1:
<class-suite>
class class2(class1):
<class suite>
class class3(class2):
<class suite>
Example 3:
class Animal:
def speak(self):
print("Animal Speaking")
#The child class Dog inherits the base class Animal
class Dog(Animal):
def bark(self):
print("dog barking")
#The child class Dogchild inherits another child class Dog
class DogChild(Dog):
def eat(self):
print("Eating bread...")
d = DogChild()
[Link]()
[Link]()
[Link]()
Output:
dog barking
Animal Speaking
Eating bread...
Hierarchical Inheritance:
When more than one derived class are created from a single base this type of inheritance
is called hierarchical inheritance. In this program, we have a parent (base) class and two
child (derived) classes.
Example 4:
# Python program to demonstrate Hierarchical inheritance
# Base class
class Parent:
def func1(self):
print("This function is in parent class.")
# Derived class1
class Child1(Parent):
def func2(self):
print("This function is in child 1.")
# Derivied class2
class Child2(Parent):
def func3(self):
print("This function is in child 2.")
# Driver's code
object1 = Child1()
object2 = Child2()
object1.func1()
object1.func2()
object2.func1()
object2.func3()
Polymorphism
Polymorphism contains two words "poly" and "morphs". Poly means many, and morph means
shape. By polymorphism, we understand that one task can be performed in different ways. For
example - you have a class animal, and all animals speak. But they speak differently. Here, the
"speak" behaviour is polymorphic in a sense and depends on the animal. So, the abstract
"animal" concept does not actually "speak", but specific animals (like dogs and cats) have a
concrete implementation of the action "speak"
# A simple Python function to demonstrate
# Polymorphism
def add(x, y, z = 0):
return x+y+z
# Driver code
print(add(2, 3))
print(add(2, 3, 4))
Encapsulation
Encapsulation is one of the fundamental concepts in object-oriented programming (OOP). It
describes the idea of wrapping data and the methods that work on data within one unit.
This puts restrictions on accessing variables and methods directly and can prevent the
accidental modification of data.
To prevent accidental change, an object’s variable can only be changed by an object’s method.
Those types of variables are known as private variables.
A class is an example of encapsulation as it encapsulates all the data that is member functions,
variables, etc. The goal of information hiding is to ensure that an object’s state is always valid
by controlling access to attributes that are hidden from the outside world.
Protected members (in C++ and JAVA) are those members of the class that cannot be accessed
outside the class but can be accessed from within the class and its subclasses. To accomplish
this in Python, just follow the convention by prefixing the name of the member by a single
underscore “_”.
# Python program to
# demonstrate protected members
# Creating a base class
class Base:
def __init__(self):
# Protected member
self._a = 2
# Creating a derived class
class Derived(Base):
def __init__(self):
# Calling constructor of
# Base class
Base.__init__(self)
print("Calling protected member of base class: ",
self._a)
# Modify the protected variable:
self._a = 3
print("Calling modified protected member outside
class: ",
self._a)
obj1 = Derived()
obj2 = Base()
# Calling protected member
# Can be accessed but should not be done due to convention
print("Accessing protected member of obj1: ", obj1._a)
# Accessing the protected variable outside
print("Accessing protected member of obj2: ", obj2._a)
Index Object-oriented Programming Procedural Programming
1. Object-oriented programming is the Procedural programming uses a list of
problem-solving approach and used where instructions to do computation step by
computation is done by using objects. step.
2. It makes the development and maintenance In procedural programming, It is not easy
easier. to maintain the codes when the project
becomes lengthy.
3. It simulates the real world entity. So real- It doesn't simulate the real world. It works
world problems can be easily solved on step by step instructions divided into
through oops. small parts called functions.
4. It provides data hiding. So it is more secure Procedural language doesn't provide any
than procedural languages. You cannot proper way for data binding, so it is less
access private data from anywhere. secure.
5. Example of object-oriented programming Example of procedural languages are: C,
languages is C++, Java, .Net, Python, C#, Fortran, Pascal, VB etc.
etc.
Data Abstraction
Data abstraction and encapsulation both are often used as synonyms. Both are nearly
synonyms because data abstraction is achieved through encapsulation.
Abstraction is used to hide internal details and show only functionalities. Abstracting
something means to give names to things so that the name captures the core of what a
function or a whole program does.
Errors and exceptions
Errors
Errors or mistakes in a program are often referred to as bugs. They are almost always
the fault of the programmer. The process of finding and eliminating errors is called
debugging. Errors can be classified into three major groups:
Syntax errors
Runtime errors
Logical errors
When a Python program meets an error, it stops the execution of the rest of the
program. An error in Python might be either an error in the syntax of an expression or a
Python exception.
Syntax Errors:
A programming language is very strict and unambiguous, so a syntax error occurs
when we don’t respect or follow the language vocabulary. As a result, the program
can’t run, and a useful error message will print instead.
Common Python syntax errors include:
• leaving out a keyword
• putting a keyword in the wrong place
• leaving out a symbol, such as a colon, comma or brackets
• misspelling a keyword
• incorrect indentation
• • empty block
Example of Syntax Error
#Python code after removing the syntax error
string = "Python Exceptions"
for s in string:
if (s != o:
print( s )
Output:
if (s != o:
^
SyntaxError: invalid syntax
Python will do its best to tell you where the error is located, but sometimes its messages
can be misleading: for example, if you forget to escape a quotation mark inside a string
you may get a syntax error referring to a place later in your code, even though that is
not the real source of the problem.
If you can’t see anything wrong on the line specified in the error message, try
backtracking through the previous few lines. As you program more, you will get better
at identifying and fixing errors.
Here are some examples of syntax errors in Python:
myfunction(x, y):
return x + y
else:
print("Hello!")
if mark >= 50
print("You passed!")
if arriving:
print("Hi!")
esle:
print("Bye!")
if flag:
print("Flag is set!")
Here are the changes made:
1. Added the colon at the end of the def statement for defining the myfunction function.
2. Removed the else statement without a corresponding if statement.
3. Added a colon at the end of the if statement for checking if mark is greater than or
equal to 50.
4. Defined the variables mark, arriving, and flag before using them in the code.
5. Corrected the spelling of else in the last else statement.
6. Added a colon at the end of the if statement for checking the value of the flag
variable.
Runtime Errors
If a program is syntactically correct – that is, free of syntax errors – it will be run by the
Python interpreter. However, the program may exit unexpectedly during execution if it
encounters a runtime error – a problem which was not detected when the program was
parsed, but is only revealed when a particular line is executed. When a program comes
to a halt because of a runtime error, we say that it has crashed.
Some examples of Python runtime errors:
• division by zero
• performing an operation on incompatible types
• using an identifier which has not been defined
• accessing a list element, dictionary value or object attribute which doesn’t exist
• trying to access a file which doesn’t exist
Runtime errors often creep in if you don’t consider all possible values that a variable
could contain, especially when you are processing user input. You should always try to
add checks to your code to make sure that it can deal with bad input and edge cases
gracefully. We will look at this in more detail in the chapter about exception handling.
Find the runtime error—
dividend = float(input("Please enter the dividend: "))
divisor = float(input("Please enter the divisor: "))
quotient = dividend / divisor
quotient_rounded = [Link](quotient)
Logical errors
Logical errors are the most difficult to fix. They occur when the program runs without
crashing, but produces an incorrect result. The error is caused by a mistake in the
program’s logic. You won’t get an error message, because no syntax or runtime error
has occurred. You will have to find the problem on your own by reviewing all the
relevant parts of your code – although some tools can flag suspicious code which looks
like it could cause unexpected behaviour.
Sometimes there can be absolutely nothing wrong with your Python implementation of
an algorithm – the algorithm itself can be incorrect. However, more frequently these
kinds of errors are caused by programmer carelessness. Here are some examples of
mistakes which lead to logical errors:
• using the wrong variable name
• indenting a block to the wrong level
• using integer division instead of floating point division
• getting operator precedence wrong.
• making a mistake in a boolean expression
If you misspell an identifier name, you may get a runtime error or a logical error,
depending on whether the misspelled name is defined.
Example of logical errrors--
product = 0
for i in range(10):
product *= i
sum_squares = 0
for i in range(10):
i_sq = i**2
sum_squares += i_sq
nums = 0
for num in range(10):
num += num
Logical Error: In this section, you're initializing product to 0 and then multiplying it by i
within the loop. However, since you're starting with 0 and never updating product, the
final value of product will always remain 0, regardless of the iterations.
product = 0
for i in range(10):
product *= i
Logical Error: In this section, you're trying to calculate the sum of squares of numbers
from 0 to 9. However, the calculation of i_sq is inside the loop, but the addition of i_sq
to sum_squares is outside the loop. This means that only the last calculated square
(9**2) will be added to sum_squares, and the previous calculations will be discarded.
sum_squares = 0
for i in range(10):
i_sq = i**2
sum_squares += i_sq
Logical Error: In this section, you're initializing nums to 0 and then updating num by
adding it to itself within the loop. This will lead to num being doubled with each
iteration, but you're not storing the values anywhere.
nums = 0
for num in range(10):
num += num
What is an Exception?
An exception in Python is an incident that happens while executing a program that
causes the regular course of the program's commands to be disrupted. When a Python
code comes across a condition it can't handle, it raises an exception.
An object in Python that describes an error is called an exception.
When a Python code throws an exception, it has two options: handle the exception
immediately or stop and quit.
Python automatically generates many exceptions and errors. Eg:Runtime exceptions,
generally a result of programming errors, such as:
• Reading a file that is not present
• Trying to read data outside the available index of a list
• Dividing an integer value by zero
• Example 1: The FilenotfoundError is raised when a file in not
present on the disk
fp =open("[Link]","r")
if fp: print("file is opened successfully")
Output: FileNotFoundError: [Errno 2] No such file or
directory: '[Link]'
The try and except Block to Handling Exceptions
When an exception occurs, Python stops the program execution and generates an
exception message. It is highly recommended to handle exceptions.
The doubtful code that may raise an exception is called risky code.
To handle exceptions we need to use try and except block. Define risky code that can
raise an exception inside the try block and corresponding handling code inside the
except block.
Syntax:
try :
# statements in try block
except :
# executed when exception occured in try block
try-except block
The try block is for risky code that can raise an exception and the except block to
handle error raised in a try block.
For example, if we divide any number by zero, try block will throw ZeroDivisionError,
so we should handle that exception in the except block.
When we do not use try…except block in the program, the program terminates
abnormally, or it will be nongraceful termination of the program.
---Example when we do not use try…except block for handling exceptions.
a=10
b=0
c=a/b
print("a/b = %d" % c)
Output:
Traceback (most recent call last):
File "E:/demos/[Link]", line 3, in <module>
c=a/b
ZeroDivisionError: division by zero
We can see in the above code when we are divided by 0; Python throws an exception
as ZeroDivisionError and the program terminated abnormally.
We can handle the above exception using the try…except block. See the following
code.
try:
a=10
b=0
c=a/b
print("The answer of a divide by b:", c)
except:
print("Can't divide with zero. Provide different
number")
Output:
print("Can't divide with zero. Provide different number")
• Catching Specific Exceptions
It is good practice to specify an exact exception that the except clause should
catch.
For example, to catch an exception that occurs when the user enters a non-numerical
value instead of a number, we can catch only the built-in ValueError exception that
will handle such an event properly.
We can specify which exception except block should catch or handle. A try block can
be followed by multiple numbers of except blocks to handle the different exceptions.
But only one exception will be executed when an exception occurs.
Example
In this example, we will ask the user for the denominator value. If the user enters a
number, the program will evaluate and produce the result.
If the user enters a non-numeric value then, the try block will throw a ValueError
exception, and we can catch that using a first catch block ‘except ValueError’ by
printing the message ‘Entered value is wrong’.
And suppose the user enters the denominator as zero. In that case, the try block will
throw a ZeroDivisionError, and we can catch that using a second catch block by
printing the message ‘Can’t divide by zero’.
try:
a = int(input("Enter value of a:"))
b = int(input("Enter value of b:"))
c = a/b print("The answer of a divide by b:", c)
except ValueError: print("Entered value is wrong")
except ZeroDivisionError: print("Can't divide by zero")
Output 1:
Enter value of a:Ten
Entered value is wrong
Output 2:
Enter value of a:10
Enter value of b:0
Can't divide by zero
Output 3:
Enter value of a:10
Enter value of b:2
The answer of a divide by b: 5.0
Python Raise an Exception
The raise statement in Python is used to raise an exception. Try-except blocks can be used to
manage exceptions, which are errors that happen while a programme is running. When an
exception is triggered, the programme goes to the closest exception handler, interrupting the
regular flow of execution.
• o The raise keyword is typically used inside a function or method, and is used to indicate
an error condition.
• o We can throw an exception and immediately halt the running of your programme by
using the raise keyword.
• o Python looks for the closest exception handler, which is often defined using a try-except
block, when an exception is triggered.
• o If an exception handler is discovered, its code is performed, and the try-except block's
starting point is reached again.
• o If an exception handler cannot be located, the software crashes and an error message
appears.
Example :
# Python program to raise an exception # check_age function
checks the age
def check_age(age):
if age < 18:
raise Exception(" Age must be 18 or above. ")
else: print(" Age is valid. ")
try:
check_age(17)
except Exception as e:
print(" An error occurred: ", e)
Output:
An error occurred: Age must be 18 or above.
The check age method in this illustration accepts the input age and throws an exception if age is
less than 18. The try block catches this exception, and the unless block prints the error message.
This demonstrates how you can raise and handle exceptions in Python.