About cookies on this site Our websites require some cookies to function properly (required). In addition, other cookies may be used with your consent to analyze site usage, improve the user experience and for advertising. For more information, please review your options. By visiting our website, you agree to our processing of information as described in IBM’sprivacy statement. To provide a smooth navigation, your cookie preferences will be shared across the IBM web domains listed here.
Tutorial
Object-oriented programming in Python
Build flexible and reusable code to develop more advanced modules and libraries
Object-oriented programming (OOP) is a programming paradigm based on the concept of objects, which can contain data in the form of attributes and code in the form of methods. Another definition of OOP is a way to build flexible and reusable code to develop more advanced modules and libraries such as Numpy and Pandas.
Everything in Python is an object. For instance, string and list are Python objects. A class is like a blueprint for creating objects. It is easy to maintain code that is written using OOP techniques because of the modular structure. Programs are more secure with the encapsulation approach used in OOP.
This tutorial discusses the fundamentals of object-oriented programming such as classes, objects, methods, polymorphism, and inheritance to give you a good foundation in OOP.
Class
The present data structures in Python like integers and strings are designed to represent something like the number of employees and the name of an employee. A class in OOP is like a blueprint for objects, and you can develop your own data structure by using OOP. For example, you could create an Employee class to track properties about the employee, such as the name or salary.
The class keyword is used to create a class in Python. The class name follows the class keyword followed by the colon. The body of the class starts on a new line and is indented one tab from the class keyword.
Constructor is a method that is called by default whenever you create an object from a class. You must create a method with keyword init to create a constructor. In the following example, I create a class named Employee with two class attributes status and number_of_employee as well as two instance attributes employee_id and name. The Employee class also contains the give_info() method.
class Employee:
#class attributes
status = "active"
number_of_employee = 0
def __init__(self, employee_id, name):
self.employee_id = employee_id #instance attribute
self.name = name #instance attribute
Employee.number_of_employee += 1
#instance method
def give_info(self):
print("Name:",self.name,"\nID:",self.employee_id)
The first employee_id in the self.employee_id = employee_id expression is an instance attribute or variable, and the second employee_id is a parameter. The same thing is also true for the name variable. When creating an object using a class, you can write emre = Employee("101", "Emre Kutluğ"), 101 and Emre Kutluğ are arguments.
Object
As I said earlier, a class is like a blueprint for creating objects. The relationship between a class and an object can be understood by looking at the relationship between an animal and Yogi Bear. Yogi Bear is an animal. An animal is an abstract concept. It is implemented in the form of Yogi Bear or Mickey Mouse. Therefore, we need to create an object of a class before we can use its methods and attributes.
An object is also called an instance. Therefore, the process of creating an object of a class is called instantiation. In Python, to create an object of a class, you must write the class name followed by opening and closing parenthesis. In the following example, I create an object of Employee class.
emre = Employee("101", "Emre Kutluğ")
I can use the type method to check the type of the object. As you see in the following example, the type of emre object is a class Employee.
Input:
type(emre)
Output:
__main__.Employee
You can access class and instance attributes and call a instance method by using the class's object. To do so, you must write the object name, followed by the dot (.) operator and the name of the attribute or the method that you want to access or call. Look at the following examples.
Input:
emre.status
Output:
'active'
Input:
emre.number_of_employee
Output:
1
Input:
emre.employee_id
Output:
'101'
Input:
emre.give_info()
Output:
Name: Emre Kutluğ
ID: 101
Attributes
You can use the built-in dir() function to see all of the attributes and methods of an object. There are some built-in attributes and methods in Python. The following example shows all of the attributes and methods of the emre object. The examples with double underscores in front are built-in attributes and methods.
Input:
dir(emre)
Output:
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'employee_id',
'give_info',
'name',
'number_of_employee',
'status']
There are two types of attributes that are class and instance attributes. The value of class attributes is the same across all objects, but the value of instance attributes can change across objects. Instance attributes are declared inside any method while class attributes are declared outside of methods. The instance attributes are referred by using the self keyword, while class attributes are referred by the class name inside the method. In the previous Employee class, status and number_of_employee are class attributes, name and employee_id are instance attributes. In the following example, we look first at the value of the number_of_employee attribute, and then we create another object from the Employee class.
Input:
emre.number_of_employee
Output:
1
Input:
emma = Employee("102", "Emma Stone")
Input:
emma.give_info()
Output:
Name: Emma Stone
ID: 102
When we look at the value of number_of_employee in the following example, we see 2 in the output because the number_of_employee attribute is a class attribute. Therefore, it's shared between the objects.
Input:
emma.number_of_employee
Output:
2
Methods
As mentioned previously, you can implement the functions of an object using methods. I used the objects of a class to call the methods so far, but there is another type of method that is a static method that can be called directly using the class name. Static methods can only access class attributes. In the following example, I add a static method to the Employee class.
Input:
class Employee:
#class attributes
status = "active"
number_of_employee = 0
def __init__(self, employee_id, name):
self.employee_id = employee_id #instance attribute
self.name = name #instance attribute
Employee.number_of_employee += 1
#instance method
def give_info(self):
print("Name:",self.name,"\nID:",self.employee_id)
@staticmethod
def get_class_objective():
message = "The objective of this Employee class is to organize employee information with more modular manner"
print (message)
Input:
Employee.get_class_objective()
Output:
The objective of this `Employee` class is to organize employee information in a more modular manner.
Global versus local variables
The attributes of a class are also referred to as variables. There are two types of variables: local and global. Local variables in a class are variables that can only be accessed inside the method where it is defined. Therefore, you cannot access a message variable outside of the get_class_objective() method. When you try to access it, it gives the AttributeError, as seen in the following example.
Input:
emre.message
Output:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-15-35255f09e347> in <module>
----> 1 emre.message
AttributeError: 'Employee' object has no attribute 'message'
Global variables are defined outside of any method, and they can be accessed anywhere in the class. Status and number_of_employee
are global variables in the previous example, so we can access them as shown in the following example.
Input:
emre.status
Output:
'active'
Encapsulation
There are three main concepts in object-oriented programming: Encapsulation, Inheritance, and Polymorphism. Encapsulation refers to data hiding. In OOP, one class should not have direct access to the data of the other class, or the access should be controlled through instance methods. You can use private variables and properties to control access to class data. To define a private variable, you can put two underscores in front of the variable name. For instance, __age is a private variable.
You can create a property for the age attribute that implements this logic, as shown in the following code. A property has three parts. You must define the attribute, which is age in the following example. Next, you must define the property for the attribute using the @property decorator. Finally, you must create a property setter, which is the @age.setter descriptor in the following example. You can say that the age of employees should always between 18 - 99. If a user tries to enter a value for the age attribute that is less than 18 or greater than 99, there's an error and an object from the Employee class cannot be created. However, if the value is between 18 - 99, an object can be created.
Input:
class Employee:
#class attributes
status = "active"
number_of_employee = 0
def __init__(self, employee_id, name, age):
self.employee_id = employee_id #instance attribute
self.name = name #instance attribute
self.age = age #instance attribute
Employee.number_of_employee += 1
# Creates model property
@property
def age(self):
return self.__age
# Create property setter
@age.setter
def age(self, age):
if age < 18:
raise Exception('An Employee\'s age cannot be lower than 18')
elif age > 99:
raise Exception('An Employee\'s age cannot be upper than 99')
else:
self.__age = age
#instance method
def give_info(self):
print("Name:",self.name,"\nID:",self.employee_id)
@staticmethod
def get_class_objective():
message = "The objective of this Employee class is to organize employee information with more modular manner"
print (message)
Input:
child = Employee("103", "Eric Cartman", 12)
Output:
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
<ipython-input-18-1bdb73cbdda9> in <module>
----> 1 child = Employee("103", "Eric Cartman", 12)
<ipython-input-17-686e6830c0b5> in __init__(self, employee_id, name, age)
8 self.employee_id = employee_id #instance attribute
9 self.name = name #instance attribute
---> 10 self.age = age #instance attribute
11 Employee.number_of_employee += 1
12
<ipython-input-17-686e6830c0b5> in age(self, age)
21 def age(self, age):
22 if age < 18:
---> 23 raise Exception('An Employee\'s age cannot be lower than 18')
24 elif age > 99:
25 raise Exception('An Employee\'s age cannot be upper than 99')
Exception: An Employee's age cannot be lower than 18
Inheritance
Inheritance in OOP is similar to real-world inheritance where a child inherits some of the characteristics from his parents, in addition to his own unique characteristics. The class that inherits another class is called a child class, and the class that is inherited by another class is called a parent class. The following code shows an example of inheritance.
Input:
# Create Class Manager that inherits Employee
class Manager(Employee):
def set_team_size(self, team_size):
self.team_size = team_size
In the previous example, I create a Manager class that inherits the Employee class. To inherit a class, you must write the parent class name inside the parenthesis that follows the child class name. The Manager class can access all of the attributes and methods of the parent Employee class, like shown in the following example.
Input:
muge = Manager("104", "Müge Özkan", 30)
Input:
muge.name
Output:
'Müge Özkan'
Input:
muge.status
Output:
'active'
Input:
muge.get_class_objective()
Output:
'The objective of this Employee class is to organize employee information with more modular manner'
The Manager class also has its own method set_team_size() in addition to the Employee class' methods and attributes. You can set the team size of the object of the Manager class as in the following example. As a side note, one class can have more than two parent or child classes.
Input:
muge.set_team_size(10)
Input:
muge.team_size
Output:
10
Polymorphism
Polymorphism refers to the ability of an object to act in different ways. There are two types of polymorphism: method overriding and method overloading.
Method overriding
Method overriding means having a method with the same name in the child class as in the parent class. The definitions of such methods are different in parent and child classes, but the name remains the same. If you remember, we had a give_info() method in the Employee class. We can override this method in the child Manager class to give team size information about manager objects.
Input:
class Manager(Employee):
team_size = 10
def set_team_size(self, team_size):
self.team_size = team_size
def give_info(self):
print("Name:",self.name,"\nID:",self.employee_id,"\nTeam Size:",self.team_size)
Input:
muge = Manager("104", "Müge Özkan", 30)
Input:
muge.give_info()
Output:
Name: Müge Özkan
ID: 104
Team Size: 10
Input:
emre.give_info()
Output:
Name: Emre Kutluğ
ID: 101
As you see in the previous example, the give_info() method is being called through both parent and child classes, but they behave differently because the child class has overridden parent class's method.
Method overloading
You can overload any method by changing the number or types of the arguments when you are calling such methods and the methods behave differently. In the following example, if we call the calculate_salary() method with one argument, it returns that argument. However, if we call that method with two arguments, it returns a summation of the two arguments.
Input:
class Manager(Employee):
team_size = 10
def set_team_size(self, team_size):
self.team_size = team_size
def give_info(self):
print("Name:",self.name,"\nID:",self.employee_id,"\nTeam Size:",self.team_size)
def calculate_salary(self, salary, bonus=None):
if bonus is not None:
salary += bonus
return salary
Input:
muge = Manager("104", "Müge Özkan", 30)
Input:
muge.calculate_salary(12345)
Output:
12345
Input:
muge.calculate_salary(12345, 678)
Output:
13023
Conclusion
In this tutorial, I explained object-oriented programming concepts such as classes, objects, attributes, and methods. Then, I continued with Encapsulation, Inheritance, and Polymorphism, which are pillars of OOP. OOP is one of the most commonly used programming paradigms. Therefore, most of the modern programming languages like Python support object-oriented programming.