Unit 2
Unit 2
Programming
OOP Features
Main Concepts of Object-Oriented Programming (OOPs)
• Class
• Objects
• Polymorphism
• Compile-Time (Function Overloading, Operator Overloading)
• Run-Time (Method Overriding)
• Encapsulation
• Inheritance
• Data Abstraction
2
OOP, Defining a Class
• Python was built as a procedural language
– OOP exists and works fine, but feels a bit more "tacked on"
– Java probably does classes better than Python (gasp)
• Declaring a class:
class name:
statements
3
Fields
name = value
– Example: point.py
class Point: 1 class Point:
x = 0 2 x = 0
y = 0 3 y = 0
# main
p1 = Point()
p1.x = 2
p1.y = -5
4
Using a Class
import class
– client programs must import the classes they use
point_main.py
1 from Point import *
2
3 # main
4 p1 = Point()
5 p1.x = 7
6 p1.y = -3
7 ...
8
9 # Python objects are dynamic (can add fields any time!)
10 p1.name = "Tyler Durden"
5
Object Methods
def name(self, parameter, ..., parameter):
statements
6
"Implicit" Parameter (self)
• Java: this, implicit
public void translate(int dx, int dy) {
x += dx; // this.x += dx;
y += dy; // this.y += dy;
}
7
Exercise Answer
point.py
1 from math import *
2
3 class Point:
4 x = 0
5 y = 0
6
7 def set_location(self, x, y):
8 self.x = x
9 self.y = y
10
11 def distance_from_origin(self):
12 return sqrt(self.x * self.x + self.y * self.y)
13
14 def distance(self, other):
15 dx = self.x - other.x
16 dy = self.y - other.y
17 return sqrt(dx * dx + dy * dy)
8
Calling Methods
• A client can call the methods of an object in two ways:
– (the value of self can be an implicit or explicit parameter)
1) object.method(parameters)
or
2) Class.method(object, parameters)
• Example:
p = Point(3, -4)
p.translate(1, 5)
Point.translate(p, 1, 5)
9
Constructors
• Constructors are generally used for instantiating an object. The
task of constructors is to initialize(assign values) to the data
members of the class when an object of the class is created.
11
Complete Point Class
point.py
1 from math import *
2
3 class Point:
4 def __init__(self, x, y):
5 self.x = x
6 self.y = y
7
8 def distance_from_origin(self):
9 return sqrt(self.x * self.x + self.y * self.y)
10
11 def distance(self, other):
12 dx = self.x - other.x
13 dy = self.y - other.y
14 return sqrt(dx * dx + dy * dy)
15
16 def translate(self, dx, dy):
17 self.x += dx
18 self.y += dy
19
20 def __str__(self):
21 return "(" + str(self.x) + ", " + str(self.y) + ")"
12
Python Class and Object Example1
Dog.py
1 class Dog:
2 # class attribute
3 attr1 = "mammal"
4 # Instance attribute
5 def __init__(self, name):
6 self.name = name
7
8 # Object instantiation
9 Rodger = Dog("Rodger")
10
11 Tommy = Dog("Tommy")
12
13 # Accessing class attributes
14 print("Rodger is a", Rodger.attr1)
15 print("Rodger is a", Tommy.attr1)
16
17
18 # Accessing instance attributes
19 print("My name is", Rodger.name)
20 print("My name is", Tommy.name)
21
13
Python Class and Object Example2
Dog1.py
1 class Dog1:
2 # class attribute
3
4 attr1 = "mammal“
5
6 # Instance attribute
7 def __init__(self, name):
8 self.name = name
9 def speak(self):
10
11 print("My name is {}".format(self.name))
12
13 # Object instantiation
14 Rodger = Dog1("Rodger")
15 Tommy = Dog1("Tommy")
16
17
18 # Accessing class methods
19 Rodger.speak()
20 Tommy.speak()
21
14
Encapsulation
• Encapsulation is the mechanism for restricting the access to some
of an objects's components, this means, that the internal
representation of an object can't be seen from outside of the
objects definition.
• C++, Java, and C# rely on the public, private, and protected
keywords in order to implement variable scoping and
encapsulation.
• In python, We don’t have public, protected or private keywords,
but we use underscore to restrict a variable for outside
accessibility.
15
Public, Protected and Private
• If an identifier doesn't start with an underscore character "_" it can
be accessed from outside, i.e. the value can be read and changed.
• Data can be protected by making members private or protected.
• Instance variable names starting with two underscore characters
cannot be accessed from outside of the class.
• At least not directly, but they can be accessed through private
name mangling.
• That means, private data __A can be accessed by the following
name construct: instance_name._classname__A
16
Public, Protected and Private
• If an identifier is only preceded by one underscore character, it is a
protected member.
• Protected members can be accessed like public members from
outside of class
Example:
class Encapsulation(object):
def __init__(self, a, b, c):
self.public = a
self._protected = b
self.__private = c
17
Public, Protected and Private
• The following interactive sessions shows the behavior of public, protected and
private members:
18
Public, Protected and Private
• The following table shows the different behavior Public, Protected
and Private Data:
19
Protected Members
• 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.
20
Protected Members
Example : Python program to demonstrate protected members
# Creating a base class
class Base:
def __init__(self):
# Protected member
self._a = 2
21
Protected Members
Example cont...
obj1 = Derived()
obj2 = Base()
22
Private Members
• Private members are similar to protected members, the difference
is that the class members declared private should neither be
accessed outside the class nor by any derived class.
23
Private Members
Example : Python program to demonstrate private members
# Public member
self.a = “Welcome to Python”
# Private member
self.__c = “Welcome to Python”
24
Private Members
Example cont... # Driver code
obj1 = Base()
print(obj1.a) # Works fine
print(obj1.__c) # will raise an AttributeError
obj2 = Derived()
# will also raise an AtrributeError as private member of
base class is called inside derived class
25
Naming Using Underscore(_)
• Underscore(_) can be used to name variables, functions and
classes, etc.
Single Pre Underscore:- _variable
Single Post Underscore:- variable_
Double Pre Underscores:- __variable
Double Pre and Post Underscores:- __variable__
1. _single_pre_underscore (_name)
Single Pre Underscore is used for internal use. Most of us don't use it
because of that reason.
• single pre underscore doesn't
class Test: stop you from accessing
def __init__(self): the single pre
self.name = "datacamp"
self._num = 7 obj = Test()
underscore variable.
print(obj.name) print(obj._num) • But, single pre
obj = Test() underscore effects the names
print(obj.name) that are imported from the
print(obj._num) module. 26
Naming Using Underscore(_)
_single_pre_underscore (_name) cont...
## filename:- my_functions.py
Create the following python file def func():
return “Welcome to python"
def _private_func():
return 7
27
Naming Using Underscore(_)
2. single_post_underscore (name_)
– Sometimes if you want to use Python Keywords as a variable, function
or class names, you can use this convention for that.
– You can avoid conflicts with the Python Keywords by adding
an underscore at the end of the name which you want to use.
Ex:
28
Naming Using Underscore(_)
3. Double Pre Underscore (__name)
– Double Pre Underscores are used for the name mangling.
– Name Mangling:- interpreter of the Python alters the variable name in a
way that it is challenging to clash when the class is inherited.
29
Naming Using Underscore(_)
3. Double Pre Underscore cont...
– Let's create another class by inheriting Sample class to see how
overriding works.
Ex:
30
Naming Using Underscore(_)
3. Double Pre Underscore cont...
– Can access the Double Pre Underscore variables using methods in the
class
Ex:
31
Naming Using Underscore(_)
3. Double Pre Underscore cont...
– Can also use the Double Pre Underscore for the method names.
Ex:
32
Naming Using Underscore(_)
4. Double Pre And Post Underscore (__name__)
– In Python, you will find different names which start and end with
the double underscore. They are called as magic methods or dunder
methods.
Ex:
33
Inheritance
• Inheritance is the capability of one class to derive or inherit the
properties from another class.
Python Inheritance Syntax
– Example:
class Point:
x = 0
y = 0
class Point3D(Point): # Point3D extends Point
z = 0
...
34
Calling Superclass Methods
• methods: class.method(object,
parameters)
• constructors: class.__init__(parameters)
class Point3D(Point):
z = 0
def __init__(self, x, y, z):
Point.__init__(self, x, y)
self.z = z
35
Inheritance Example
class Person: # Parent class
# Constructor
def __init__(self, name):
self.name = name
36
Subclassing (Calling
constructor of parent class)
• A child class needs to identify which class is its parent class. This can be done by
mentioning the parent class name in the definition of the child class.
Eg: class subclass_name(superclass_name):
# Python code to demonstrate how parent constructors are called.
# parent class
class Person:
def __init__(self, name, idnumber):
self.name = name
self.idnumber = idnumber # child class
def display(self): class Employee(Person):
print(self.name) def __init__(self, name, idnumber, salary, post):
print(self.idnumber) self.salary = salary
self.post = post
class B(A):
def __init__(self, roll):
self.roll = roll
object = B(23)
print(object.roll) # No Error
print(object.name) # Error
38
Types of Inheritance in Python
Single Inheritance: Single inheritance enables a derived class to inherit
properties from a single parent class, thus enabling code reusability and the
addition of new features to existing code.
# 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() Output:
object.func1()
object.func2()
39
Types of Inheritance in Python
Multiple Inheritance: When a class can be derived from more than one base
class this type of inheritance is called multiple inheritances. (Unlike java,
python shows multiple inheritance.)
# Python program to demonstrate multiple inheritance
# Base class1
class Mother:
mothername = ""
def mother(self):
print(self.mothername)
# Base class2
# Driver's code
class Father:
s1 = Son()
fathername = ""
s1.fathername = "RAM"
def father(self):
s1.mothername = "SITA"
print(self.fathername)
s1.parents()
# Derived class
class Son(Mother, Father):
def parents(self):
print("Father :", self.fathername)
print("Mother :", self.mothername)
40
Types of Inheritance in Python
Multiple Inheritance: When the method is overridden in both classes
Method Resolution Order (MRO) will take place from left to right.
class Class1: class Class1:
def m(self): def m(self):
print("In Class1") print("In Class1")
42
Types of Inheritance in Python
# Python program to demonstrate multilevel inheritance
# Base class
class Grandfather:
def __init__(self, grandfathername):
self.grandfathername = grandfathername
# Intermediate class
class Father(Grandfather):
def __init__(self, fathername, grandfathername):
self.fathername = fathername
# invoking constructor of Grandfather class # Driver code
Grandfather.__init__(self, grandfathername) s1 = Son('Prince', 'Rampal',
# Derived class 'Lal mani')
class Son(Father): print(s1.grandfathername)
def __init__(self, sonname, fathername, s1.print_name()
grandfathername):
self.sonname = sonname
# invoking constructor of Father class
Father.__init__(self, fathername, grandfathername)
def print_name(self):
print('Grandfather name :', self.grandfathername)
print("Father name :", self.fathername)
print("Son name :", self.sonname)
43
Types of Inheritance in Python
Hierarchical Inheritance: When more than one derived class are created from
a single base class, this type of inheritance is called hierarchical inheritance.
# 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): # Driver's code
def func2(self): object1 = Child1()
print("This function is in child 1.") object2 = Child2()
# Derived class2 object1.func1()
class Child2(Parent): object1.func2()
def func3(self): object2.func1()
print("This function is in child 2.") object2.func3()
44
Types of Inheritance in Python
Hybrid Inheritance: Inheritance consisting of multiple types of inheritance is
called hybrid inheritance.
Hybrid
Inheritance
Multiple
Inheritance
45
Types of Inheritance in Python
# Python program to demonstrate Hybrid inheritance
46
Function Overloading
Like other languages do, python does not support method overloading by
default. But there are different ways to achieve method overloading in Python.
The problem with method overloading in Python is that we may overload the
methods but can only use the latest defined method.
Example 2:
47
How to Achieve Function
Overloading in Python
Method1 :
If we want to implement the concept of function overloading, we need to set
the default values of the parameters of the function as None. By setting the
value of functional parameters as None, we get the option of calling the
function either with or without the parameter.
Method2:
By Using Multiple Dispatch Decorator
Multiple Dispatch Decorator Can be installed by:
48
How to Achieve Function
Overloading in Python
Using Method 1: Calculate the area of figures(triangle, rectangle, square).
49
How to Achieve Function
Overloading in Python
Using Method 2: Using Multiple Dispatch Decorator
from multipledispatch import dispatch
>> product(2,3)
>> Product(2,3,4)
>> product(2.2,3.4,2.3)
50
Method Overriding
Method overriding is an ability of any object-oriented programming language
that allows a subclass or child class to provide a specific implementation of a
method that is already provided by one of its super-classes or parent classes.
When a method in a subclass has the same name, same parameters or signature
and same return type(or sub-type) as a method in its super-class, then the
method in the subclass is said to override the method in the super-class.
51
Method Overriding
Method Overriding Example:
# Defining parent class
>> class Parent():
def __init__(self):
self.value = "Inside Parent"
# Parent's show method
def show(self):
print(self.value)
# Defining child class
>> class Child(Parent):
def __init__(self):
self.value = "Inside Child"
# Child's show method
def show(self):
print(self.value)
>> obj1.show()
>> obj2.show()
52
Method Overriding with Multiple
Inheritance
Method Overriding with Multiple Inheritance Example:
>> class Parent1():
# Parent1's show method
def show(self):
print("Inside Parent1")
>> obj.show()
>> obj.display()
53
Method Overriding with
Multilevel Inheritance
Method Overriding with Multilevel Inheritance Example:
>> class Parent():
# Parent's show method
def display(self):
print("Inside Parent")
>> g = GrandChild()
>> g.show()
>> g.display()
54
Calling the Parent’s method
within the overridden method
Parent class methods can also be called within the overridden methods. This can
generally be achieved by two ways.
1. Using Classname: 2. Using Super()
class Parent():
class Parent():
def show(self):
print("Inside Parent") def show(self):
print("Inside Parent")
class Child(Parent):
class Child(Parent):
def show(self):
def show(self):
# Calling the parent's class
# method # Calling the parent's class
Parent.show(self) # method
print("Inside Child") super().show()
print("Inside Child")
# Driver's code
# Driver's code
obj = Child() obj = Child()
obj.show() obj.show()
55
Operator Overloading
Operator Overloading means giving extended meaning beyond their predefined
operational meaning. For example operator + is used to add two integers as well
as join two strings and merge two lists.
>> print(1 + 2)
56
How to Overload an Operator
To perform operator overloading, Python provides some special function or
magic function that is automatically invoked when it is associated with that
particular operator.
• There by changing this magic method’s code, we can give extra meaning to the
+ operator.
57
How to Overload an Operator
Program to overload binary + operator
class A:
def __init__(self, a):
self.a = a
print(ob1 + ob2)
print(ob3 + ob4)
58
How to Overload an Operator
Program to overload comparison operators
class A:
def __init__(self, a):
self.a = a
def __gt__(self, other):
if(self.a>other.a):
return True
else:
return False
ob1 = A(2)
ob2 = A(3)
if(ob1>ob2):
print("ob1 is greater than ob2")
else:
print("ob2 is greater than ob1")
59
How to Overload an Operator
Overloading equality and less than operators :
>> class A:
def __init__(self, a):
self.a = a
def __lt__(self, other):
if(self.a<other.a):
return "ob1 is lessthan ob2"
else:
return "ob2 is less than ob1"
def __eq__(self, other):
if(self.a == other.a):
return "Both are equal"
else:
return "Not equal"
>> ob1 = A(2)
>> ob2 = A(3)
>> print(ob1 < ob2)
61
Exceptions
What is an exception?
Even if a statement or
expression is syntactically correct, it
may cause an error when an attempt
is made to execute it. Errors
detected during execution are
called exceptions
62
Exceptions
For Example
63
Handling Exceptions
It is possible to write programs
that handle selected exceptions.
Look at the following example,
which asks the user for input until a
valid integer has been entered, but
allows the user to interrupt the
program (using Control-C or
whatever the operating system
supports); note that a user-
generated interruption is signalled
by raising the KeyboardInterrupt 64
Handling Exceptions
For Example
65
Handling Exceptions
66
Handling Exceptions
68
The except Clause with No Exceptions
69
The except Clause with No Exceptions
71
Examples
72
Example
73
Example
74
Catching Specific Exception
try:
# statement(s)
except IndexError:
# statement(s)
except ValueError:
# statement(s)
75
Example : Multiple Exception Handling
76
Example : Multiple Exception Handling
77
Try with Else Clause
In python, you can also use the else clause
on the try-except block which must be present
after all the except clauses. The code enters the
else block only if the try clause does not raise an
exception.
78
raise statement
79
raise statement
81
raise Example 2
82
Some common exceptions
83
Some common exceptions
IOError
If the file cannot be opened.
ImportError
If python cannot find the module.
ValueError
Raised when a built-in operation or
function receives an argument that has the
right type but an inappropriate value.
84
Some common exceptions
KeyboardInterrupt
Raised when the user hits the interrupt key
(normally Control-C or Delete).
EOFError
Raised when one of the built-in functions
(input() or raw_input()) hits an end-of-file
condition (EOF) without reading any data
85
Thank You
86