Python Classes and Objects

Python Classes And Objects Thumbnail

Python is an Object Oriented Programming(OOP) language. Object Oriented Programming is an essential concept in programming, it allows us to break the programs into reusable components, and implement the concepts like Polymorphism, Encapsulation, Inheritance, and Data Abstraction.

The classes and objects are the building block of object-oriented programing.

It provides a way to concatenate several methods and properties together to create a blueprint(i.e. class) which is then used to create its multiple instances(i.e. objects) which increases the reusability and reduces the redundancy in the code. It also helps in debugging, i.e., as the code organizes in classes is much easier to debug than unorganized code.

This tutorial will cover everything you need to know about classes and objects in python.

What is a Python Class?

A class is a blueprint from which objects are created. It can create a user-defined structure that contains data members(i.e variables or properties) and member functions (ie. method to manipulate data members).

For example, we can have a class Employee with employee_id as the property and work() as the function. We can create different Employee objects from this class.

The properties are generally at the object level, so the employee_id can be different for other Employee objects.

The functions are at the object level or the class level. These functions mostly work on object properties and perform specific tasks.

How to Create a Class in Python

We can create a Python class using the class reserved keyword. Let’s look at an empty class with no properties or functions.

class Employee:
    pass

Having an empty class doesn’t give us any benefits. So, let’s add some class properties and functions to it.

class Employee:
    employee_id = 0

    def work(self):
        print(f'{self.employee_id} is working')

How to instantiate a class in Python?

When we create a Python class, it automatically creates a default no-argument constructor for it. We can invoke this constructor to create the instance of the class. This instance is referred to as the object of the class.

emp = Employee()
print(type(emp))
emp.work()

Output:

<class '__main__.Employee'>
0 is working

The built-in type() function returns the type of the object. It’s used to get the Class information of an object.

Class Objects 

An object is an instance of a class that can have access to its properties and methods.

When a class is instantiated using the class keyword, it creates an object. A single class can have multiple objects and each object shares the class variables, class methods, and behavior.

In the above example, the emp is considered an object of employee class.

What is the base class in Python?

Did you think about how the Employee class automatically got a no-args constructor?

It’s because Python supports inheritance and every class in Python is automatically inherited from the base class “object”. When we don’t define a constructor for the class, the “object” class constructor is used to create the instance of the class.

Defining a Constructor for the Class

If you notice the Employee class implementation, there is no way to set the employee_id value. We can define a separate method to set the employee_id value. But, it’s the mandatory property of the Employee object. The best place to set these properties is through the constructor.

Python constructor is a special function that gets called when we create the instance of the class. This function name is always __init__ and it can have any number of parameters. The first parameter is always the object itself, usually named the self-variable.

Let’s go ahead and create a constructor for the Employee class. We expect the caller program to pass the employee_id value as an argument.

class Employee:

    def __init__(self, i):
        self.employee_id = i

    def work(self):
        print(f'{self.employee_id} is working')


emp = Employee(100)
emp.work()

Output:

100 is working

Note: The earlier code to create the Employee object will not work now because the Employee constructor is expecting an argument. If we call Employee(), it will raise TypeError: init() missing 1 required positional argument: ‘id’.

Can we have multiple constructors in Python?

Unlike other popular Object-oriented programming languages, Python doesn’t support method overloading and constructor overloading.

However, it won’t throw any error if we define multiple constructors in the class. The last constructor will overwrite the earlier defined constructor definition. Let’s look at it with an example.

class Employee:

    def __init__(self, id):
        self.employee_id = id
    
    # this will overwrite earlier defined constructor
    def __init__(self, id, n):  
        self.employee_id = id
        self.emp_name = n

    def work(self):
        print(f'{self.emp_name}[{self.employee_id}] is working')


emp = Employee(100, 'Pankaj')
emp.work()

emp = Employee(100)  # will raise Error
emp.work()

Output:

Pankaj[100] is working
Traceback (most recent call last):
  File "/Users/pankaj/Documents/PycharmProjects/AskPython/hello-world/class_examples.py", line 19, in <module>
    emp = Employee(100)
TypeError: __init__() missing 1 required positional argument: 'n'

Class Variables vs Instance Variables

When a variable is defined at the class level, it’s called a class variable. When the variable is defined in the constructor, it’s called an instance variable.

The class variables are shared across all the instances of the class whereas instance variables are unique to the instance. So, it’s very important to understand when to use the class variable and when to use the instance variable.

In the earlier examples, the employee_id attribute is unique to an Employee instance, so it’s better to have it as an instance variable and defined in the constructor.

Let’s say we want to keep track of the number of employee instances created and the employee ids’ allocated. In this case, we can use class variables to store this data and update it by the instances.

class Employee:
    count = 0
    ids_list = []

    def __init__(self, i):
        self.id = i
        Employee.count += 1
        self.ids_list.append(i)


for x in range(0, 10):
    emp = Employee(x)

print(f'Number of employees created = {Employee.count}')
print(f'List of employee ids allocated = {Employee.ids_list}')

emp = Employee(1000)
print(f'List of employee ids allocated = {emp.ids_list}')

Output:

Python Class Object Example
Python Class Object Example
Number of employees created = 10
List of employee ids allocated = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
List of employee ids allocated = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000]

Note: We can access class variables through the class name as well as the instance variable.

Summary

Classes and objects are the essential concepts that lead to object-oriented programming. Object-oriented helps to reduce the redundancy in the code and provides many capabilities such as Polymorphism, Encapsulation, Inheritance, and Data Abstraction. It helps to make the application stable and scalable. It also helps debug the code, as the code organised in the form of classes and objects is much easier to debug. 

Hope this tutorial helps you to understand the concept of classes and objects in Python.

References

Python.org Docs