0% found this document useful (0 votes)
6 views

Day-15 Python Constructors

Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Day-15 Python Constructors

Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 19

Python Constructors – default and

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.

1. What is a Constructor in Python?


Constructor is used for initializing the instance members when we create
the object of a class.

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)

# creating object of the class. This invokes constructor


obj = DemoClass()

# calling the instance method using the object obj


obj.read_number()

100
Other Example
class student:

name = ""
id=""

def __init__(self, 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()

1.1 Syntax of constructor declaration


As we have seen in the above example that a constructor always has a
name init and the name init is prefixed and suffixed with a double
underscore(__). We declare a constructor using def keyword, just like
methods.

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.

2.1 Python – default constructor example


Note: An object cannot be created if we don’t have a constructor in our
program. This is why when we do not declare a constructor in our program,
python does it for us. Lets have a look at the example below.
Example: When we do not declare a constructor
In this example, we do not have a constructor but still we are able to create
an object for the class. This is because there is a default constructor
implicitly injected by python during program compilation, this is an empty
default constructor that looks like this:

def __init__(self):
# no body, does nothing.
Source Code:

class DemoClass:
num = 101

# a method
def read_number(self):
print(self.num)

# creating object of the class


obj = DemoClass()

# calling the instance method using the object obj


obj.read_number()
Output:

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)

# creating object of the class


obj = DemoClass()

# calling the instance method using the object obj


obj.read_number()
Output:

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)

# creating object of the class


# this will invoke parameterized constructor
obj = DemoClass(55)

# calling the instance method using the object obj


obj.read_number()

# creating another object of the class


obj2 = DemoClass(66)

# calling the instance method using the object obj


obj2.read_number()
Output:

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.

Catching Exceptions in Python


In Python, exceptions can be handled using a try statement.

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.

# import module sys to get the type of exception


import sys
randomList = ['a', 0, 2]
for entry in randomList:
try:
print("The entry is", entry)
r = 1/int(entry)
break
except:
print("Oops!",sys.exc_info()[0],"occured.")
print("Next entry.")
print()
print("The reciprocal of",entry,"is",r)

Output
The entry is a

Oops! <class 'ValueError'> occured.

Next entry.

The entry is 0

Oops! <class 'ZeroDivisionError' > occured.

Next entry.

The entry is 2

The reciprocal of 2 is 0.5

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.

Catching Specific Exceptions in Python


In the above example, we did not mention any exception in the except clause.

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 (TypeError, ZeroDivisionError):


# handle multiple exceptions
# TypeError and ZeroDivisionError
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.

>>> raise KeyboardInterrupt


Traceback (most recent call last):
...
KeyboardInterrupt

>>> raise MemoryError("This is an argument")


Traceback (most recent call last):
...
MemoryError: This is an argument

>>> 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.

Here is an example of file operations to illustrate this.

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.

Python Custom Exceptions


Python has many built-in exceptions which forces your program to output an error when
something in it goes wrong.

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.

>>> class CustomError(Exception):


... pass
...

>>> raise CustomError


Traceback (most recent call last):
...
__main__.CustomError

>>> raise CustomError("An error occurred")


Traceback (most recent call last):
...
__main__.CustomError: An error occurred
Here, we have created a user-defined exception called CustomError which is derived
from the Exception class. This new exception can be raised, like other exceptions,
using the raisestatement with an optional error message.

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.

Example: User-Defined Exception in Python


In this example, we will illustrate how user-defined exceptions can be used in a program
to raise and catch errors.

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.

# define Python user-defined exceptions


class Error(Exception):
"""Base class for other exceptions"""
pass

class ValueTooSmallError(Error):
"""Raised when the input value is too small"""
pass

class ValueTooLargeError(Error):
"""Raised when the input value is too large"""
pass

# our main program


# user guesses a number until he/she gets it right

# you need to guess this number


number = 10

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()

print("Congratulations! You guessed it correctly.")

Here is a sample run of this program.

Enter a number: 12

This value is too large, try again!

Enter a number: 0
This value is too small, try again!

Enter a number: 8

This value is too small, try again!

Enter a number: 10

Congratulations! You guessed it correctly.

Here, we have defined a base class called Error.

The other two exceptions (ValueTooSmallError and ValueTooLargeError) that are


actually raised by our program are derived from this class. This is the standard way to
define user-defined exceptions in Python programming, but you are not limited to this
way only.

Visit this page to learn in detail about how you can handle exceptions in Python.

Python Operator Overloading


What is operator overloading in Python?
Python operators work for built-in classes. But same operator behaves differently with
different types. For example, the + operator will, perform arithmetic addition on two
numbers, merge two lists and concatenate two strings.

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.

Special Functions in Python


Class functions that begins with double underscore __ are called special functions in
Python. This is because, well, they are not ordinary. The __init__() function we
defined above, is one of them. It gets called every time we create a new object of that
class. There are a ton of special functions in Python.

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

Now let's try the print() function again.

>>> 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)'

So, when you do str(p1) or format(p1), Python is internally doing p1.__str__().


Hence the name, special functions.

Ok, now back to operator overloading.

Overloading the + Operator in Python


To overload the + sign, we will need to implement __add__() function in the class. With
great power comes great responsibility. We can do whatever we like, inside this
function. But it is sensible to return a Point object of the coordinate sum.

 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

Now let's try that addition again.

>>> p1 = Point(2,3)
>>> p2 = Point(-1,2)
>>> print(p1 + p2)
(1,5)

What actually happens is that, when you do p1 + p2, Python will


call p1.__add__(p2) which in turn is Point.__add__(p1,p2). Similarly, we can
overload other operators as well. The special function that we need to implement is
tabulated below.

Operator Overloading Special Functions in Python

Operator Expression Internally

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)

Floor Division p1 // p2 p1.__floordiv__(p2)

Remainder
p1 % p2 p1.__mod__(p2)
(modulo)

Bitwise Left Shift p1 << p2 p1.__lshift__(p2)

Bitwise Right Shift p1 >> p2 p1.__rshift__(p2)

Bitwise AND p1 & p2 p1.__and__(p2)

Bitwise OR p1 | p2 p1.__or__(p2)

Bitwise XOR p1 ^ p2 p1.__xor__(p2)

Bitwise NOT ~p1 p1.__invert__()

Overloading Comparison Operators in Python


Python does not limit operator overloading to arithmetic operators only. We can
overload comparison operators as well.

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

Try these sample runs in Python shell.

>>> Point(1,1) < Point(-2,-3)


True

>>> Point(1,1) < Point(0.5,-0.2)


False

>>> Point(1,1) < Point(1,1)


False

Similarly, the special functions that we need to implement, to overload other comparison
operators are tabulated below.

Comparision Operator Overloading in Python


Operator Expression Internally

Less than p1 < p2 p1.__lt__(p2)

Less than or equal to p1 <= p2 p1.__le__(p2)

Equal to
p1 == p2 p1.__eq__(p2)

Not equal to p1 != p2 p1.__ne__(p2)

Greater than p1 > p2 p1.__gt__(p2)

Greater than or equal to p1 >= p2 p1.__ge__(p2)

You might also like