Object Oriented Programming
Python, a multi-paradigm programming language supports several coding techniques. Making objects is one of the common ways to tackle a programming language. This is known an Objected Oriented approach to programming.
In python, any object has two characteristics:
- attributes
- behavior Example: Suppose a car has the following properties:
- make, model, year, odometer_reading as attributes
- read_odometer, get_desriptive_name as methods
Class
A class can be defined as the blueprint for an obect. We can think of class as a blueprint with labels. It contains all the details about the make, modle, year, odometer_reading, etc. Based on these descriptions, we can study about the car. Here, a car is an object.
The example for class of car can be:
1
2
class Car:
pass
Here, we define the empty class Car
` using the class keyword. We create instances from classes. An instance is a particular object that was made from a certain class.
Object
An instantiation of a class results in an object (instance). Only the object’s description is defined when a class is created. As a result, no storage or RAM is allocated.
An example of a car class object is:
1
obj = Car()
Here, obj
is an object of a class Car
.
Let’s say we know specifics about cars. We will now demonstrate how to create the Car
class and its objects.
Example 1: Creating Class and Object in Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Car;
#class attribute
type='electric'
#instance attribute
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
#instantiate the Car class
car1 = Car('Audi', 'A4', 2016)
car2 = Car('Toyta', 'T1', 2017)
#access the class attributes
print(f'Car1 is of type: {car1.__class__.type}')
print(f'Car2 is of type: {car2.__class__.type}')
#access the instance attributes
print(f'{car1.make}'s model is {car1.model} and it was made in {car1.year}')
print(f'{car2.make}'s model is {car2.model} and it was made in {car2.year}')
Output:
Audi is of type: electric
Audi is of type: electric
Audi's model is A4 and it was made in 2016
Toyota's model is T1 and it was made in 2017
In the above program, we created a class with the name Car
. Then we defined the class attribute type
and the instance attributes make
, model
and year
. The class attribute is defined outside the __init__
method and the instance attributes are defined within the __init__
method of the class. The __init__
method is the one that is called first whenever the object is first created.
We then create two instances car1
and car2
of the Car
class.
We can access the class attribute using __class__.species
. Class attributes are the same for all instances of a class. Similarly, we use car1.make, car1.model and car1.year to access the instance characteristics. But each instance of a class has a unique set of instance characteristics.
Methods
Methods are simple the functions that are defined within the body of a class. They are used to define the behaviors of an object.
Example2: Creating Methods in Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Car():
#instance attributes
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
#instance methods
def get_descriptive_name(self):
long_name = f"{self.year} {self.make} {self.model}"
return long_name
#instantiate the object
my_new_car = Car('Audi', 'A4', 2016)
#calling our instance methods
print(my_new_car.get_descriptive_name())
Output: Audi A4 2016
Inheritance
By leveraging the details of an existing class without changing it, a new class can be created through inheritance. A derived class has just been created (or child class).The current class is a base class in a similar way (or parent class).
Example 3: Use of inheritance in Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
class Car():
def __init__(self, make, model,year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = str(self.year) + " " + self.make + " " + self.model
return long_name.title()
def read_odometer(self):
print("This car has run {} miles on it".format(str(self.odometer_reading)))
def update_odometer(self, mileage):
if mileage < self.odometer_reading:
print("You can't roll back an odometer")
else:
self.odometer_reading = mileage
def increment_odometer(self, miles):
self.odometer_reading += miles
def fill_gas_tank(self):
"""Electric cars don't have gas tanks."""
print("This car doesn't need a gas refill!")
class Battery():
def __init__(self, battery_size = 70):
self.battery_size = battery_size
def describe_battery(self):
print("This car has a {} -kwh batteyr.".format(self.battery_size))
def get_range(self):
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge."
print(message)
def upgrade_battery(self):
if self.battery_size != 85:
self.battery_size = 85
class ElectricCar(Car):
def __init__(self,make,model,year):
super().__init__(make,model,year)
self.battery = Battery()
def get_descriptive_name(self):
long_name = "This is an electric car " + str(self.year) + " " + self.make + " " + self.model
return long_name.title()
def fill_gas_tank(self):
print("This car doesn't need a gas tank!")
def is_this_electric(self):
print('Yes, this is electric')
my_tesla = ElectricCar('tesla', 'model s', 2016)
my_tesla.read_odometer()
print(my_tesla.get_descriptive_name())
my_tesla.fill_gas_tank()
Output:
This car has run 0 miles on it.
This Is An Electric Car 2016 Tesla Model S
This car doesn't need a gas tank!
Yes, this is electric.
In the above program, we created three classes i.e Car
(parent class), Battery
, and ElectricCar
(child class). The child class inherits the functions of the parent class. We can see this from the read_odometer()
method.
Again, the child class modifies the behavior of the parent class. We can see this from them get_descriptive_name()
method. Furthermore, we extedn the functions of the parent class by creating a new is_this_electric()
method.
In the __init__()
method of the child class, we also employ the super()
function. This enables us to call the parent class’s __init__()
method form the child class.
Encapsulation
We can limit access to methods and variables in Python by using OOP. Encapsulation is the process of preventing direct data change. In Python, we use the underscore prefix to indicateprivate attributes, such as single _
or double __
underscores.
Example 4: Data Encapsulation In Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class IceCream:
def __init__(self):
self.__maxprice = 200
def sell(self):
print(f'Selling Price: {self.__maxprice}')
def setmaxPrice(self, price):
self.__maxprice = price
icecream = IceCream()
icecream.sell()
# change the price
icecream.__maxprice = 250
icecream.sell()
# using setter function
icecream.setmaxPrice(250)
icecream.sell()
Output:
Selling Price: 200
Selling Price: 200
Selling Price: 250
In the above program, we defined an IceCream
class. We used __init__()
method to store the maximum selling price of IceCream
.
1
icecream.__maxprice = 250
Here, we have tried to modify the value of __maxprice
outside of the class. However, since __maxprice
is a private variable, this modification is not seen on output. As practiced aboce, we have to change the value of __maxprice
using a setter function like setmaxPrice()
which takes price
as its parameter.
Polymorphism
In Object Oriented Programming, the ability to use a common interface for many forms is known as polymorphism (data types). Consider that there are various shape alternatives when we need to color a form (rectangle, square, circle). However, we could color any form using the same technique. This concept is known as Polymorphism
Example 5: Using Polymorphism in Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Car():
def __init__(self, make, model,year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = str(self.year) + " " + self.make + " " + self.model
print(long_name.title())
class ElectricCar(Car):
def __init__(self,make,model,year):
super().__init__(make,model,year)
def get_descriptive_name(self):
long_name = "This is an electric car " + str(self.year) + " " + self.make + " " + self.model
print(long_name.title())
#common interface
def get_description(obj):
obj.get_descriptive_name()
#instantiate objects
car1 = Car('Audi', 'A1', 2016)
car2 = ElectricCar('Tesla', 'T1', 2020)
#passing the object
get_description(car1)
get_description(car2)
Output:
2016 Audi A1
This Is An Electric Car 2020 Tesla T1
In the above program, we defined two classes:- Car
and ElectricCar
. The get_descriptive_name()
method is share by all of them. However, each Car shares a different version of the function.
Now, to use Polymorphism
, we develop a common interface called get_description()
, which accepts any object and calls the objects get_descriptive_name()
method. As a result, the get_description()
method successfully executed when supplied it the car1
and car2
objects.