Day-15 Python Constructors
Day-15 Python Constructors
parameterized
A constructor is a special kind of method which is used for initializing the
instance variables during object creation. In this guide, we will see what is a
constructor, types of it and how to use them in the python programming
with examples.
For example:
Here we have a instance variable num which we are initializing in the
constructor. The constructor is being invoked when we create the object of
the class (obj in the following example).
class DemoClass:
# constructor
def __init__(self):
# initializing instance variable
self.num=100
# a method
def read_number(self):
print(self.num)
100
Other Example
class student:
name = ""
id=""
self.name = name
self.id=id
def displayuser(self):
print("name")
print(id)
emp1= student("san",121)
emp2 =student("ajeeth",122)
emp1.displayuser()
emp2.displayuser()
def __init__(self):
# body of the constructor
2. Types of constructors in Python
We have two types of constructors in Python.
1. default constructor – this is the one, which we have seen in the above
example. This constructor doesn’t accept any arguments.
2. parameterized constructor – constructor with parameters is known as
parameterized constructor.
def __init__(self):
# no body, does nothing.
Source Code:
class DemoClass:
num = 101
# a method
def read_number(self):
print(self.num)
101
Example: When we declare a constructor
In this case, python does not create a constructor in our program.
class DemoClass:
num = 101
# non-parameterized constructor
def __init__(self):
self.num = 999
# a method
def read_number(self):
print(self.num)
999
2.2 Python – Parameterized constructor
example
When we declare a constructor in such a way that it accepts the arguments
during object creation then such type of constructors are known as
Parameterized constructors. As you can see that with such type of
constructors we can pass the values (data) during object creation, which is
used by the constructor to initialize the instance members of that object.
class DemoClass:
num = 101
# parameterized constructor
def __init__(self, data):
self.num = data
# a method
def read_number(self):
print(self.num)
55
66
Exception handling
What are exceptions in Python?
Python has many built-in exceptions which forces your program to output an error when
something in it goes wrong.
When these exceptions occur, it causes the current process to stop and passes it to the calling
process until it is handled. If not handled, our program will crash.
For example, if function A calls function B which in turn calls function C and an exception occurs
in function C. If it is not handled in C, the exception passes to B and then to A.
If never handled, an error message is spit out and our program come to a sudden, unexpected
halt.
A critical operation which can raise exception is placed inside the try clause and the code that
handles exception is written in except clause.
It is up to us, what operations we perform once we have caught the exception. Here is a simple
example.
Output
The entry is a
Next entry.
The entry is 0
Next entry.
The entry is 2
In this program, we loop until the user enters an integer that has a valid reciprocal. The
portion that can cause exception is placed inside try block.
If no exception occurs, except block is skipped and normal flow continues. But if any
exception occurs, it is caught by the except block.
Here, we print the name of the exception using ex_info() function inside sys module
and ask the user to try again. We can see that the values 'a' and '1.3' causes ValueError
and '0' causes ZeroDivisionError.
This is not a good programming practice as it will catch all exceptions and handle every
case in the same way. We can specify which exceptions an except clause will catch.
A try clause can have any number of except clause to handle them differently but only
one will be executed in case an exception occurs.
We can use a tuple of values to specify multiple exceptions in an except clause. Here is
an example pseudo code.
try:
# do something
pass
except ValueError:
# handle ValueError exception
pass
except:
# handle all other exceptions
pass
Raising Exceptions
In Python programming, exceptions are raised when corresponding errors occur at run
time, but we can forcefully raise it using the keyword raise.
We can also optionally pass in value to the exception to clarify why that exception was
raised.
>>> try:
... a = int(input("Enter a positive integer: "))
... if a <= 0:
... raise ValueError("That is not a positive number!")
... except ValueError as ve:
... print(ve)
...
Enter a positive integer: -2
That is not a positive number!
try...finally
The try statement in Python can have an optional finally clause. This clause is
executed no matter what, and is generally used to release external resources.
For example, we may be connected to a remote data center through the network or
working with a file or working with a Graphical User Interface (GUI).
In all these circumstances, we must clean up the resource once used, whether it was
successful or not. These actions (closing a file, GUI or disconnecting from network) are
performed in the finally clause to guarantee execution.
try:
f = open("test.txt",encoding = 'utf-8')
# perform file operations
finally:
f.close()
This type of construct makes sure the file is closed even if an exception occurs.
However, sometimes you may need to create custom exceptions that serves your
purpose.
In Python, users can define such exceptions by creating a new class. This exception
class has to be derived, either directly or indirectly, from Exception class. Most of the
built-in exceptions are also derived form this class.
When we are developing a large Python program, it is a good practice to place all the
user-defined exceptions that our program raises in a separate file. Many standard
modules do this. They define their exceptions separately
as exceptions.py or errors.py (generally but not always).
User-defined exception class can implement everything a normal class can do, but we
generally make them simple and concise. Most implementations declare a custom base
class and derive others exception classes from this base class. This concept is made
clearer in the following example.
This program will ask the user to enter a number until they guess a stored number
correctly. To help them figure it out, hint is provided whether their guess is greater than
or less than the stored number.
class ValueTooSmallError(Error):
"""Raised when the input value is too small"""
pass
class ValueTooLargeError(Error):
"""Raised when the input value is too large"""
pass
while True:
try:
i_num = int(input("Enter a number: "))
if i_num < number:
raise ValueTooSmallError
elif i_num > number:
raise ValueTooLargeError
break
except ValueTooSmallError:
print("This value is too small, try again!")
print()
except ValueTooLargeError:
print("This value is too large, try again!")
print()
Enter a number: 12
Enter a number: 0
This value is too small, try again!
Enter a number: 8
Enter a number: 10
Visit this page to learn in detail about how you can handle exceptions in Python.
This feature in Python, that allows same operator to have different meaning according
to the context is called operator overloading.
So what happens when we use them with objects of a user-defined class? Let us
consider the following class, which tries to simulate a point in 2-D coordinate system.
script.py
IPython Shell
1
2
3
4
class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
Run
Powered by DataCamp
Now, run the code and try to add two points in Python shell.
>>> p1 = Point(2,3)
>>> p2 = Point(-1,2)
>>> p1 + p2
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'
Whoa! That's a lot of complains. TypeError was raised since Python didn't know how to
add two Point objects together.
However, the good news is that we can teach this to Python through operator
overloading. But first, let's get a notion about special functions.
Using special functions, we can make our class compatible with built-in functions.
>>> p1 = Point(2,3)
>>> print(p1)
<__main__.Point object at 0x00000000031F8CC0>
That did not print well. But if we define __str__() method in our class, we can control
how it gets printed. So, let's add this to our class.
script.py
IPython Shell
1
2
3
4
5
6
7
class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x,self.y)
Run
Powered by DataCamp
>>> p1 = Point(2,3)
>>> print(p1)
(2,3)
That's better. Turns out, that this same method is invoked when we use the built-in
function str() or format().
>>> str(p1)
'(2,3)'
>>> format(p1)
'(2,3)'
script.py
IPython Shell
1
2
3
4
5
6
7
8
9
10
11
12
class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x,self.y)
def __add__(self,other):
x = self.x + other.x
y = self.y + other.y
return Point(x,y)
Run
Powered by DataCamp
>>> p1 = Point(2,3)
>>> p2 = Point(-1,2)
>>> print(p1 + p2)
(1,5)
Addition p1 + p2 p1.__add__(p2)
Subtraction p1 - p2 p1.__sub__(p2)
Multiplication p1 * p2 p1.__mul__(p2)
Power p1 ** p2 p1.__pow__(p2)
Division p1 / p2 p1.__truediv__(p2)
Remainder
p1 % p2 p1.__mod__(p2)
(modulo)
Bitwise OR p1 | p2 p1.__or__(p2)
Suppose, we wanted to implement the less than symbol < symbol in our Point class.
Let us compare the magnitude of these points from the origin and return the result for
this purpose. It can be implemented as follows.
script.py
IPython Shell
1
2
3
4
5
6
7
8
9
10
11
12
class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x,self.y)
def __lt__(self,other):
self_mag = (self.x ** 2) + (self.y ** 2)
other_mag = (other.x ** 2) + (other.y ** 2)
return self_mag < other_mag
Run
Powered by DataCamp
Similarly, the special functions that we need to implement, to overload other comparison
operators are tabulated below.
Equal to
p1 == p2 p1.__eq__(p2)