Object-Oriented Programming in Python For BracU

Download as pdf or txt
Download as pdf or txt
You are on page 1of 2

Brac University

EEE103/ECE103/CSE161: Computer Programming

Department of Electrical and Electronic Engineering

Instructor
Md. Mahmudul Islam

Introduction to OOP

Table of Contents
Brac University
EEE103/ECE103/CSE161: Computer Programming
Department of Electrical and Electronic Engineering
Instructor
Md. Mahmudul Islam
Introduction to OOP
Why Object-Oriented Programming
What is Object-Oriented Programming
4 Pillars of OOP
Why use Class?
What is Class ?
Instance
Class Vs Instance
Building our first class
Creating an Instance of that class
Class Variable vs Instance Variable
Instance Methods
Encapsulation
Abstraction
Inheritance
Multilevel Inheritance
Multiple Inheritance
Method Resolution Order (MRO)
Polymorphism
Creating a common interface
Method Overriding
References:

In [1]: from IPython.core.interactiveshell import InteractiveShell


InteractiveShell.ast_node_interactivity='all'

Why Object-Oriented Programming


Lets say you want to define a function which will apply discounts on the ticket price of a park. But the problem is there will
be three different discount rate for three different category of people where the categories are as follows: Male, Female and
children.

So, How will you do?

What is Object-Oriented Programming


Object-oriented programming is a programming paradigm that provides a means of structuring programs so that
properties and behaviors are bundled into individual objects.

In another way, object-oriented programming is an approach for modeling concrete, real-world things, like cars, as well as
relations between things, like companies and employees, students and teachers, and so on. OOP models real-world
entities as software objects that have some data associated with them and can perform certain functions.

For instance, an object could represent a person with properties like a name, age, and address and behaviors such as
walking, talking, breathing, and running. Or it could represent an email with properties like a recipient list, subject, and body
and behaviors like adding attachments and sending.

An object has two characteristics:

Attributes
Behavior

Let's take an example:

A parrot is an object, as it has the following properties:

name, age, color as attributes


singing, dancing as behavior

The concept of OOP focuses on creating reusable code. This concept is also known as DRY (Don't Repeat
Yourself)

4 Pillars of OOP
Encapsulation
Abstraction
Inheritance
Polymorphism

Why use Class?


For example, let’s say you want to track students in an university. You need to store some basic information about each
student, such as their name, age, dept, and joining year.

What can you use to do so?

One way to do this is to represent each employee as a list( or array)

asad = ["Asad Rahman", 24, "EEE", 2016]

arif = ["Arif Ahmed", 22, "CSE", 2018]

Limitations:

It will be difficult to manage if the number of employees are large


Difficult to remember what is kept in which index
Difficult to debug

Solution:

A great way to make this type of code more manageable and more maintainable is to use classes

What is Class ?
A class is a blueprint for the object. It doesn’t actually contain any data.
In class whatever functions we define are known as methods. Methods are the functionality that an object created
from a class can perform with its given data (during initialization or while performing any operation).

Instance
Instance is an object that is built from a class and contains real data.

Class Vs Instance
A class is like a form or questionnaire. An instance is like a form that has been filled out with information. Just
like many people can fill out the same form with their own unique information, many instances can be created from a
single class.
When class is defined, only the description for the object is defined. Therefore, no memory or storage is allocated.

Building our first class


In [2]: class Person:

def __init__(self,name,age,profession):
self.name=name
self.age=age
self.profession=profession

In the above program, we created a class with the name Person. Then, we define some of it's attributes. These attributes
are required for identification of a person, an object created from this class will have these characteristics.

These attributes are defined inside the __init__ method of the class. Becasue it is the method which runs as soon as the
object is created (instantiated). This method can be called as _initializer or constructor.

Then, we create instances of the Person class with required arguments.

Creating an Instance of that class


In [3]: prsn1=Person('Rafiq Alam',34,'Doctor')

prsn2=Person('Sabit Ahsan',28,'Engineer')

In [4]: print(prsn1.name)
print(prsn1.profession)

print('========================================')

print(prsn2.name)
print(prsn1.profession)

Rafiq Alam
Doctor
========================================
Sabit Ahsan
Doctor

Class Variable vs Instance Variable


Class variable is a variable that have the same value for all instances.
On the other hand instance variable is specific to a particular instance of the class

In [5]: class Person:


brain='I have brain'

def __init__(self,name,age,profession):
self.name=name
self.age=age
self.profession=profession

In [6]: prsn1=Person('Rafiq Alam',34,'Doctor')

prsn2=Person('Sabit Ahsan',28,'Engineer')

In [7]: print(prsn1.name)
print(prsn1.brain)

print('========================================')

print(prsn2.name)
print(prsn2.brain)

Rafiq Alam
I have brain
========================================
Sabit Ahsan
I have brain

Instance Methods
Instance methods are functions that are defined inside a class and can only be called from an instance of that class.
They are used to define the behaviors of an object.

In [8]: class Person:


brain='I have brain'

def __init__(self,name,age,profession):
self.name=name
self.age=age
self.profession=profession

def talk_about_you(self):
print(f"Hi, My name is {self.name}. I am {self.age} years old and I am {self.profession}")

def eat(self,food):
print(f'I am going to eat {food}')

In [9]: prsn1=Person('Rafiq Alam',34,'Doctor')

prsn2=Person('Sabit Ahsan',28,'Engineer')

In [10]: prsn1.talk_about_you()
print('=============================')
prsn2.talk_about_you()

Hi, My name is Rafiq Alam. I am 34 years old and I am Doctor


=============================
Hi, My name is Sabit Ahsan. I am 28 years old and I am Engineer

In [11]: prsn1.eat('Vegetables')

prsn2.eat('Pizza')

I am going to eat Vegetables


I am going to eat Pizza

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

In Python, we denote private attributes using underscore as the prefix i.e single _ or double __.

In [12]: class Person:

def __init__(self,name,age,profession):
self.name=name
self.__age=age
self.profession=profession

def show_age(self):
print(self.__age)

def voter_eligibility(self):
return self.__age>=18

def update_age(self,age):
self.__age=age

def talk_about_you(self):
print(f"Hi, My name is {self.name}. I am {self.age} years old and I am {self.profession}")

def eat(self,food):
print(f'I am going to eat {food}')

In [13]: prsn=Person('Sabit Ahsan',16,'Engineer')

We have the authority to change instance variables even though our object is created already.

In [14]: prsn.__dict__
prsn.profession

prsn.profession='Worker'

prsn.__dict__
prsn.profession

Out[14]: {'name': 'Sabit Ahsan', '_Person__age': 16, 'profession': 'Engineer'}

Out[14]: 'Engineer'

Out[14]: {'name': 'Sabit Ahsan', '_Person__age': 16, 'profession': 'Worker'}

Out[14]: 'Worker'

But we will be unable to access our Private Variable and can not change

In [15]: prsn.__age

---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-15-d7467a70e6d6> in <module>
----> 1 prsn.__age

AttributeError: 'Person' object has no attribute '__age'


Even if we try to assign any value to our Private variable, we are unable to do that since the name of our Private
variable changes as soon as we define our object.

Variable name that we write to assign value, stores as a new variable in our object with that variable name.

In [16]: prsn.__age=30
prsn.__age

prsn.__dict__

Out[16]: 30

Out[16]: {'name': 'Sabit Ahsan',


'_Person__age': 16,
'profession': 'Worker',
'__age': 30}
To see and change the value of our Private variable we should take help of our instance methods.

Here we have declared two instance methods for this purpose.

One will be used to show the value and another one will be used to update the value of our Private
Variable

In [17]: prsn.__dict__
prsn.show_age()
prsn.voter_eligibility()

prsn.update_age(20)

prsn.__dict__
prsn.show_age()
prsn.voter_eligibility()

Out[17]: {'name': 'Sabit Ahsan',


'_Person__age': 16,
'profession': 'Worker',
'__age': 30}
16
Out[17]: False

Out[17]: {'name': 'Sabit Ahsan',


'_Person__age': 20,
'profession': 'Worker',
'__age': 30}
20
Out[17]: True

Abstraction
Abstraction is the process of hiding the real implementation of an application from the user and emphasizing only on
usage of it. For example, consider you have bought a new electronic gadget. Along with the gadget, you get a user guide,
instructing how to use the application, but this user guide has no info regarding the internal working of the gadget.

Another example is, when you use TV remote, you do not know how pressing a key in the remote changes the channel
internally on the TV. You just know that pressing + volume key will increase the volume.

Inheritance
If you want to create a class B which will have similar attributes and methods like an existing class A besides it's own
attributes and methods. Then instead of starting from scratch for class B, you can create it by deriving it from a pre-existing
class A.

Inheritance is the process by which one class takes on the attributes and methods of another and allows us to add more. It
is a way of creating a new class for using details of an existing class without modifying it. The newly formed class is
a derived class (or child class). Similarly, the existing class is a base class (or parent class).

The child class inherits the attributes and methods of its parent class, and you can use those as if they were defined
in the child class. A child class can also override data members and methods from the parent.

New methods and attributes can also be defined in child class apart from methods inherited from parent class.

Let's Define a simple class first

In [18]: class Person:


brain='I have brain'

def __init__(self,name,age,profession):
self.name=name
self.age=age
self.profession=profession

def talk_about_you(self):
print(f"Hi, My name is {self.name}. I am {self.age} years old and I am {self.profession}")

def eat(self,food):
print(f'I am going to eat {food}')

In [19]: class Dad(Person):


def __init__(self,name,age,profession,salary):
super().__init__(name,age,profession)
self.salary=salary

def favourite_task(self):
print(f'My favourite task is watching boxing on the TV')

In [20]: dad1=Dad('Asif',30,'Engineer',30000)

dad1.talk_about_you()

dad1.eat('Pizza')

dad1.favourite_task()

Hi, My name is Asif. I am 30 years old and I am Engineer


I am going to eat Pizza
My favourite task is watching boxing on the TV

Multilevel Inheritance
It is also possible to inherit from a derived class. This is called multilevel inheritance.

In multilevel inheritance, features of the base class and the derived class are inherited into the new derived class.

In [22]: class Son(Dad):


pass

In [23]: son1=Son('Sahmim',4,'kid',0)

son1.talk_about_you()

son1.eat('Chocolates')

son1.favourite_task()

Hi, My name is Sahmim. I am 4 years old and I am kid


I am going to eat Chocolates
My favourite task is watching boxing on the TV

In [24]: help(son1)

Help on Son in module __main__ object:

class Son(Dad)
| Son(name, age, profession, salary)
|
| Method resolution order:
| Son
| Dad
| Person
| builtins.object
|
| Methods inherited from Dad:
|
| __init__(self, name, age, profession, salary)
| Initialize self. See help(type(self)) for accurate signature.
|
| favourite_task(self)
|
| ----------------------------------------------------------------------
| Methods inherited from Person:
|
| eat(self, food)
|
| talk_about_you(self)
|
| ----------------------------------------------------------------------
| Data descriptors inherited from Person:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| ----------------------------------------------------------------------
| Data and other attributes inherited from Person:
|
| brain = 'I have brain'

In the above example the Son learns to talk,eat from Person and _favouritetask from Dad

Multiple Inheritance
A class can be derived from more than one base class. This is called multiple inheritance.

In multiple inheritance, the features of all the base classes are inherited into the derived class.

Example is shown below.

Let's first define a simple class.

In [25]: class Mom:


def __init__(self,name,age,profession):
self.name=name
self.age=age
self.profession=profession

def talk_about_you(self):
print(f"Hi, My name is {self.name}. I am {self.age} years old and I am {self.profession}")

def eat(self,food):
print(f'I am going to eat {food}')

def favourite_task(self):
print(f'My favourite task is cooking, singing, dancing')

def cooking(self):
print('I know how to cook')

class Dad:
def __init__(self,name,age,profession):
self.name=name
self.age=age
self.profession=profession

def talk_about_you(self):
print(f"Hi, My name is {self.name}. I am {self.age} years old and I am {self.profession}")

def eat(self,food):
print(f'I am going to eat {food}')

def favourite_task(self):
print(f'My favourite task is watching boxing on the TV')

In [26]: dad1=Dad('Asif',30,'Engineer')

mom1=Mom('Any',28,'Doctor')

mom1.favourite_task()

mom1.cooking()

dad1.favourite_task()

My favourite task is cooking, singing, dancing


I know how to cook
My favourite task is watching boxing on the TV

In [27]: class Daughter(Dad,Mom):


pass

daughter1=Daughter('Inaya',2,'kid')

daughter1.talk_about_you()

daughter1.eat('Ice-Cream')

daughter1.favourite_task()

daughter1.cooking()

Hi, My name is Inaya. I am 2 years old and I am kid


I am going to eat Ice-Cream
My favourite task is watching boxing on the TV
I know how to cook

In [28]: help(daughter1)

Help on Daughter in module __main__ object:

class Daughter(Dad, Mom)


| Daughter(name, age, profession)
|
| Method resolution order:
| Daughter
| Dad
| Mom
| builtins.object
|
| Methods inherited from Dad:
|
| __init__(self, name, age, profession)
| Initialize self. See help(type(self)) for accurate signature.
|
| eat(self, food)
|
| favourite_task(self)
|
| talk_about_you(self)
|
| ----------------------------------------------------------------------
| Data descriptors inherited from Dad:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| ----------------------------------------------------------------------
| Methods inherited from Mom:
|
| cooking(self)

In the above example the Daughter learns to _talk,eat,favouritetask from Dad from Person, cooking from Mom and does
not learn _favouritetask from Mom

Why???

Method Resolution Order (MRO)


Method Resolution Order(MRO) denotes the way a programming language resolves a method or attribute. Python supports
classes inheriting from other classes. The class being inherited is called the Parent or Superclass, while the class that
inherits is called the Child or Subclass. In python, method resolution order defines the order in which the base classes
are searched when executing a method. First, the method or attribute is searched within a class and then it follows the
order we specified while inheriting. While inheriting from another class, the interpreter needs a way to resolve the methods
that are being called via an instance. Thus we need the method resolution order.

In [29]: help(daughter1)

Help on Daughter in module __main__ object:

class Daughter(Dad, Mom)


| Daughter(name, age, profession)
|
| Method resolution order:
| Daughter
| Dad
| Mom
| builtins.object
|
| Methods inherited from Dad:
|
| __init__(self, name, age, profession)
| Initialize self. See help(type(self)) for accurate signature.
|
| eat(self, food)
|
| favourite_task(self)
|
| talk_about_you(self)
|
| ----------------------------------------------------------------------
| Data descriptors inherited from Dad:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| ----------------------------------------------------------------------
| Methods inherited from Mom:
|
| cooking(self)

Polymorphism
Polymorphism is an ability (in OOP) to use a common interface for multiple forms (data types).

Suppose, we need to color a shape, there are multiple shape options (rectangle, square, circle). However we could use the
same method to color any shape. This concept is called Polymorphism.

Creating a common interface


In [30]: def talk(a):
return a.talk_about_you()

talk(mom1)
talk(dad1)
talk(daughter1)

Hi, My name is Any. I am 28 years old and I am Doctor


Hi, My name is Asif. I am 30 years old and I am Engineer
Hi, My name is Inaya. I am 2 years old and I am kid
In the above example we are using one single function which makes everyone to talk. So this is an example of
polymorphism.

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.

It is also an example of polymorphism because by overriding a method we are making method with the same name to
perform different operations for different class objects.

In [31]: class Daughter(Dad,Mom):


def __init__(self,name,age,profession):
super().__init__(name,age,profession)

def talk_about_you(self):
print(f"My name is {self.name}. I am {self.age} years old and I like to play all day.")

def cooking(self,dish):
print(f'I can cook Yummy {dish} for you')

daughter1=Daughter('Inaya',2,'kid')

daughter1.talk_about_you()

daughter1.eat('Ice-Cream')

daughter1.favourite_task()

daughter1.cooking('Cake')

My name is Inaya. I am 2 years old and I like to play all day.


I am going to eat Ice-Cream
My favourite task is watching boxing on the TV
I can cook Yummy Cake for you

In [32]: help(daughter1)

Help on Daughter in module __main__ object:

class Daughter(Dad, Mom)


| Daughter(name, age, profession)
|
| Method resolution order:
| Daughter
| Dad
| Mom
| builtins.object
|
| Methods defined here:
|
| __init__(self, name, age, profession)
| Initialize self. See help(type(self)) for accurate signature.
|
| cooking(self, dish)
|
| talk_about_you(self)
|
| ----------------------------------------------------------------------
| Methods inherited from Dad:
|
| eat(self, food)
|
| favourite_task(self)
|
| ----------------------------------------------------------------------
| Data descriptors inherited from Dad:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)

References:
https://www.programiz.com/python-programming/object-oriented-programming
https://realpython.com/python3-object-oriented-programming/#what-is-object-oriented-programming-in-
python
Assignment Task
1. What is Object Oriented Programming and what are the benefits of
it? What are the characteristics of an Object? Explain with relevant
examples.
2. Explain difference between Class and Instance, Class variable and
Instance variable with proper examples.
3. What is Instance Method? Explain with examples.
4. Briefly Describe the idea of Abstraction with examples.
5. Describe what is Encapsulation? How we can obtain this? give some
examples.
6. Explain Inheritance, different types of Inheritance and significance
of MRO with examples.
7. What is Polymorphism, what are the ways to achieve it? Use
necessary examples.

** Use your own example while describing.

You might also like