What is OOP?
Object-oriented programming (OOP) refers to a type of computer programming (software design) that includes or relies on the concept of classes and objects instead of functions and logic. It is used to structure a software program into simple, reusable pieces of code or blueprints (called classes) which are used to create individual instances of objects.
Why OOP?
- OOP makes code organised, reusable, and easy to maintain
- Follow the DRY method (Don't Repeat Yourself)
- Prevents unwanted access to data, or exposing proprietary code through encapsulation and abstraction.
- OOP focuses on the objects that the developers want to manipulate rather than the logic required to manipulate them.
- Code reusability
What is a class?
- In a class, everything is an object
- Classes form the blueprint for objects
- Classes determine how data and behaviours are structured
What is an object?
- Can be defined as data field that has unique attributes and behaviours
- An instantiation of a class
- When a class is defined, only the description for the object is defined. Therefore, no memory or storage is allocated.
What is an instance?
- Also called an object
- Objects are instances of types.
- 23 is an instance of the type int
- Instantiation is the creating of a predefined object.
- A realisation of a template (Class of objects)
What is a method?
- Logical sequence or action
What is the difference between instantiation and initialisation?
- Variables, properties are initialised meaning they are given an initial value.
- The act of assigning values to variables is initialisation.
- Objects are instantiated. A baby is an instance of a Human, an object is an instance of some Class.
- The act of creating an instance is instantiation.
Example:
Objects are created for specific instances of a class. You might create an animal class (blueprint) as a standard way to organise all importing information about animals, and then instantiate an individual animal as an object created from the animal class - like a fish.
- Classes (blueprint)
- Objects (instances)
- Methods (behaviours)
- Attributes (data)
With a class, we can create sketches of animals with labels. It can contain details about the name, colours and size. Based on these descriptions, we can study about each animal.
Example 1: Creating Class and Object in Python
class Animal:
# class attribute
species = "mammal"
# instance attribute
def __init__(self, name, age):
self.name = name
self.age = age
# instantiate the Animal class
dog = Animal("Fluffy", 5)
cat = Animal("Kitty", 12)
# accessing the class attributes
print("Fluffy is a {}.format(dog.__class__.species))
print("Kitty is also a {}.format(cat.__class__.species))
# accessing the instance attributes
print("{} is {} years old".format(dog.name, dog.age))
print("{} is {} years old".format(cat.name, cat.age))Which would give the following output:
Fluffy is a mammal
Kitty is also a mammal
Fluffy is 5 years old
Kitty is 12 years old In the above program, we created a class with the name Animal. Then, we defined the attributes. The attributes are a characteristic of an object.
These attributes are defined inside the __init__ method of the class. It is the initialiser method that is first run as soon as the object is created.
Then, we create instances (objects) of the Animal class. Here, cat and dog are references (value) to our new objects.
We can access the class attribute using __class__.species. Class attributes are the same for all instances of a class. Similarly, we access the instance attributes using dog.name and cat.name. However, instance attributes are different for every instance of a class.
Methods are functions defined inside the body of a class. They are used to define the behaviours of an object.
Creating methods in Python
class Animal:
# instance attribute
def __init__(self, name, age):
self.name = name
self.age = age
# instance method
def sound(self, sound):
return "A {} makes a {} sound.format(self.name, sound)
# instantiate the object
dog = Animal("Fluffy, 5)
# call our instance methods
print(dog.sound("'Bark'"))The output:
A dog makes a 'bark' soundIn the above program, we define a method sound(). These are called instance methods because they are called on an instance object i.e dog.
What is self?
def __init__(self):
- This is the short form for initialising our class (creating an object)
- By using the
selfkeyword we can access the attributes and methods of the class in python. - It binds the instance of the class to the instance method.
- This represents a constructor in Python
- We know that class is a blueprint for the objects. This blueprint can be used to create multiple numbers of objects.
What happens if we do not use self
- EDIT HERE*
Self can be avoided
The object (instance) itself is passed along as the first argument, automatically. This implicit behaviour can be avoided while making a static method.
class A(object):
@staticmethod
def stat_meth():
print("Here, no self was passed") Here, @staticmethod is a function decorator which makes stat_meth() static.
The following code instantiates the A class and calls the method.
>>> a = A()
>>> a.stat_meth()
Here, no self was passedThe implicit behaviour of passing the object as the first argument was avoided while using a static method
- Inheritance 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).
Using Inheritance in Python
# parent class
class Animal:
def __init__(self, eat, walk, hungry=True, mood): # Setting default value of hunger to True
self.eat = eat
self.walk = walk
self.hungry = hungry
self.mood = mood
# child class
class Bird(Animal):
# using super(), (temporary object of the superclass) allows us to access methods of the base class (parent class)
def __init__(self):
super().__init__()
print("I am a bird")
def tweet(self):
print("tweet tweet")
def fly(self):
print("I am a free bird")
pippa = Bird()
pippa.tweet()In the above program, we created two classes i.e. Animal (parent class) and Penguin (child class). The child class inherits the functions of parent class.
The child class modified the behaviour of the parent class. We also extended the functions of the parent class, by creating new methods like tweet() and fly().
We used the super() function inside the __init__() method. This allows us to run the __init__() method of the parent class inside the child class.
- Method of data hiding, provides greater security
- Other objects do not have access to it
- Python does not have the private keyword, unlike some other object oriented languages.
- In python, we can restrict access to methods and variables. This prevents data from being modified (encapsulation).
- In python, we denote
access modifiers using underscore_or dunder (double underscore)__` as the prefix. - We use
access modifiersto change the default scope of variables. - Private variables
__can only be accessed inside the class - Protected variables
_can be accessed within the same package.
class Robot(object):
def __init__(self):
self.a = 123
self.b = 123
self.__c = 123
obj = Robot()
print(obj.a)
print(obj._b)
print(obj.__c)Outcome:
123
123
Traceback (most recent call last):
File "test.py", line 10, in <module>
print(obj.__c)
AttributeError: 'Robot' object has no attribute '__c' _ Single underscore denotes private variable. It should not be accessed directly.
__ Dunder or double underscore also denotes private variable.
We use name mangling, a technique to rewrite the attribute name and helps to access class variables from outside the class.
- Poly means many
- Morph means change
- Polymorphism refers to the ability of an object taking many forms.
- Python being an OOP supports Polymorphism through Method overriding and operator overloading.
- Polymorphism can be achieved through inheritance - Method overriding
- Method overriding provides ability to change the implementation of a method in a child class which is already defined in one of its super class or parent class.
- If there is a method in a super class the method having the same name number of arguments in a child class is said to be overriding the parent class method.
- We can use the concept of polymorphism while creating class methods as Python allows different classes to have methods with the same name.
- We can then later generalise calling these methods by disregarding the object we are working with.
## Example of class polymorphism and inheritance
from math import pi
class Shape:
def __init__(self, name):
self.name = name
def area(self):
pass
def fact(self):
return "I am a two-dimensional shape."
def __str__(self):
return self.name
class Square(Shape):
def __init__(self, length):
super().__init__("Square")
self.length = length
def area(self):
return self.length**2
def fact(self):
return "Squares have each angle equal to 90 degrees."
class Circle(Shape):
def __init__(self, radius):
super().init__("Circle")
self.radius = radius
def area(self):
return pi*self.radius**2
a = Square(4)
b = Circle(7)
print(b)
print(b.fact())
print(a.fact())
print(b.area())Output
Circle
I am a two-dimenional shape.
Squares have each angle equal to 90 degrees.
153.93804002589985Methods such as __str__(), which have not been overridden in the child classes, are used from the parent class.
The fact() method for object a(Square class) is overridden. However, fact() method for object b has not been overridden. It is inheriting from the Parent Shape class.
- Abstraction focuses on hiding the internal implementations of a process or method from the user. In this way, the user knows what he is doing but not how the work is being done.
- Using a car as an analogy. We drive without knowing what is going on underneath. We use the breaks to stop the car but we don't know how the breaks work.
- Another example is a TV set. We watch films without knowing the inner details of how TV works.
- In Python, abstraction is achieved by using abstract classes and interfaces.
- Objects can take on more than one form depending on the context
- The program determines which meaning or usage is necessary for each execution of that object, cutting down need to duplicate code.
- OOP makes the program easy to understand as well as efficient
- The class is shareable, therefore the code can be reused.
- Data is safe and secure with data abstraction.
- Polymorphism allows the same interface for different objects (implement the same functionality), so programmers can write efficient code.
- Encapsulation: only exposes selected information to the outside world.
Exercises for OOP classes HERE
More exercises for OOP classes HERE
Exercises for Inheritance HERE
Exercises for Polymorphism HERE


