Working with Classes in Python

Bashir Alam

Bashir Alam

5
(1)

Python is an Object-Oriented Programming Language. That means that Python implements a programming paradigm based on “objects,” where every “object” can store some data and the code to modify it. Class is a description of the “object” that defines attributes that characterize the object and the methods that this object implements. This tutorial will cover Python classes in detail, define classes, use constructors, implement inheritance, polymorphism, and cover some other important aspects of classes by examples.

Python Classes

Classes provide us a way to describe the data and functionality of the objects. Simply speaking, class is a way of describing the world around us. For example, you may define a class Car with attributes like color, model, and actions like increase or decrease the car’s speed.

Defining a new class in Python allows us to create a new type of object. A user-defined class describes the data that the class object should store and methods and can be used to manage that data. A user-defined class is a primitive data structure like list, string, and number classes, but it can store and process more complex information.

Class definition in Python

The simplest form of class definition syntax in Python looks like this:

class ClassName:
    <statement....>
    ...
    ...
    <statement....>

class is a keyword that you use to create a new class definition in Python. The statements inside a class are defining variables or functions.

The best practice is to use a docstring as the first statement in class to describe it.

class ClassName:
    '''This is a class that I had created'''
    ...
    ...
    <statement....>

Docstrings are written inside a triple single (''') or double (""") quotes.

Every Python class has special attributes and methods that you can access by putting double underscores (__) in front and after them, for example, __doc__, __init__() and many others. For example, __doc__ the attribute contains the docstring of the class:

class ClassName:
    '''This is a class that I had created'''

print(ClassName.__doc__)

Class vs. instance attributes in Python

There are two types of attributes available in Python classes:

  • An instance attribute is a Python variable belonging to one, and only one, object. This variable is defined inside the constructor function of the class and only accessible in the scope of the object.
  • A class attribute is a Python variable that belongs to a class itself rather than a particular object. It is defined outside the constructor function of the class and shared between all the objects of this class.

Let’s illustrate the differences by example:

class Person:
    '''This class defines a Person'''
    age = 18

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

In the example above:

  • age – is a class attribute defined outside of the class constructor
  • name – is an instance attribute defined in the class constructor

Attribute referencing in Python classes

Attribute references in classes use the standard syntax used by all attribute references in Python. For example, class_obj.name is a valid attribute reference. Here’s how you can get access to class attributes:

class ClassName:
    '''This is a class that I had created'''
    number = 7
    name = "MyName"

print(ClassName.number)
print(ClassName.name)
Attribute referencing in Python classes

Constructors in Python classes

Class functions that begin with a double underscore (__) that have special meaning in Python. One of such functions is __init__(). This special function is called whenever a new object of a class is initiated, and it is called a constructor of the class. In the following example, we will create a new class named Person and use a constructor to assign the name and gender of a person.

class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

Note: self is always the first argument you need to define in the constructor or any function in the class. It references the instance of the class and always points to the current object. 

We can get access to any class instance attribute or function using self.

Here’s an example:

class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def Introduction(self):
        print("Hello! My name is", self.name)

person1 = Person("Bashir", "Male")
person2 = Person("Bibisoro", "Female")

person1.Introduction()
person2.Introduction()
Self-in-constructor

In the above example, we create two objects: person1 and person2 and get access to the names of the objects using self keyword.

You may redefine self keyword, but make sure that it is still your first argument in the function or the class’s constructor. Let’s modify our previous example to illustrate such behavior: 

class Person:
    def __init__(Noself, name, gender):
        Noself.name = name
        Noself.gender = gender
    def Introduction(abc):
        print("Hello! My name is", abc.name)

person1 = Person("Bashir", "Male")
person2 = Person("Bibisoro", "Female")

person1.Introduction()
person2.Introduction()
Accessing Python class variables without self

Note: it is a good practice not to redefine the default self keyword to make it easier for other developers to read your code in the future.

Class vs. instance in Python

A class is a blueprint for the instance that should be defined. It does not contain actual data. It is just a code of the template or definition. For example, the class of Person contains the attribute name and gender but does not contain the actual values for name and gender variables.

An instance of the class is the actual object that contains real data and functions definitions. An instance of Person class is no longer a blueprint. It contains the name of a person like Bashir and gender like Male.

Methods in Python classes

In Python, class methods are functions that are defined within the class. For example, Introduction() from our code snippet is a class method.

Another example of the method declaration in the class:

class Person:
    def hello(self):
        return "Hello there!"
Declaring method in Python class example

In this example, class Person contains a definition of the method hello() that supposed to return the "Hello there!" string when this method is called.

Modifying class instance attributes in Python

Once the class instance is created, you can easily change its attributes. Here’s an example:

class Car:
    wheel = 4
    color = "red"

car1 = Car
print(car1.wheel)
print(car1.color)

# now we will change the properties and will print
car1.wheel = 3
car1.color = "blue"
print(car1.wheel)
print(car1.color)
Modifying class instance attributes in Python

We can always change attributes of objects using the obj.propertyName syntax as shown above.

Deleting class attributes in Python

In Python, we can use keyword del if we need to delete the attribute of the class:

class Car:
    wheel = 4
    color = "red"

del Car.color

print(Car.color)
Deleting class attributes in Python

In the example above, we deleted the color attribute, and when we tried to get access to it, we got an error that says that the Car class has no attribute color.

Deleting class object in Python

Class objects can also be deleted in the same way as the properties. Use del keyword to delete the declaration of the class within your Python program:

class Car:
    wheel = 4
    color = "red"

del Car

print(Car.color)
Deleting class object in Python

Inheritance in Python

Inheritance is a feature of a class in Python to inherit all methods and attributes from another class. When describing an inheritance, we usually speak about a parent class or a base class that shares its attributes and methods with the child or a derived class.

Innheritance-diagram

We are using inheritance every time we need to extend the behavior of the base class without copy-pasting its code completely.  

Here is a Python syntax for defining inheritance between classes:

class ParentClass:
    website = "hands-on.cloud"

class ChildClass(ParentClass):
    def print_website_name(self):
        print(f'Website name: {self.website}')

child_class = ChildClass()
child_class.print_website_name()

In the example above, the ChildClass will always have the website attribute even if it has not been defined.

Parent class syntax

Any class can be defined as a parent class in Python. The syntax for a parent class is similar to any other normal class. Here’s an example of the Person class which will be a parent class in our example:

class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def namPritning(self):
        print(self.name)
    def genderPrinting(self):
        print(self.gender)

man1 = Person("Bashir", "Male")
man1.namPritning()
man1.genderPrinting()
Parent class syntax

Child class syntax

A child class declaration in Python is similar to any class but with the difference that it takes the parent class as a parameter to inherit all functions and variables.

Take a look at the example below:

class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def namePrinting(self):
        print(self.name)
    def genderPrinting(self):
        print(self.gender)

class Shopkeeper(Person):
    pass

SK = Shopkeeper("Armio", "Male")
SK.namePrinting()
SK.genderPrinting()
Child class syntax

Inheritance example

Now, let’s take one more example to understand the inheritance in detail.

Let’s create a ParentClass and define some methods within it.

class ParentClass():
    def __init__(self, name):
        print("Constructor of parent class")
    def main(self):
        print("This is main method of parent class")
Inheritance example - Parent class

Now let’s create a child class. Remember that we need to provide a ParentClass as a parameter in a child class:

class ChildClass(ParentClass):
    def child(self):
        return True
Inheritance example - Child class

Now, let’s use the inherited function from the ParentClass in the ChildClass:

class ParentClass():
    def __init__(self, name):
        print("Constructor of parent class")
    def main(self):
        print("This is main method of parent class")

class ChildClass(ParentClass):
    def child(self):
        return True

x = ChildClass
x.main("name")
Inheritance example - Using parent class function

Here you can see that we created a new object x which inherits all the properties of ParentClass. We can now easily get access to the functionality of ParentClass from our ChildClass.

Overriding base class behavior

We can always redefine inherited attributes and functions in the child class. For example, if you want to print out “This is the main method of Child class.” instead of “This is the main method of the parent class,” you need to create the main method inside our child class and redefine its behavior.

class ParentClass():
    def __init__(self, name):
        print("Constructor of parent class")
    def main(self):
        print("This is main method of parent class")

class ChildClass(ParentClass):
    def main(self):
        print("This is main method of Child class")

x = ChildClass
x.main("name")
child-class-inherited-property-change

Multiple inheritance in Python

We had seen how we could inherit the functionality of one parent class inside a child class through the inheritance. Python also provides us the ability to inherit the functionality of multiple classes. Multiple inheritances mean that we can get access to properties and functions of many base classes from our child class.

Multiple inheritance in Python diagram

The syntax of such inheritance is simple. In the definition of the child class, you have to provide all base classes as parameters. 

Here’s the syntax of multiple inheritances:

The syntax of multiple inheritance

Now, let take a look at the implementation example of multiple inheritances:

class ParentClass():
    def parent1():
        print("Parent 1 is printing")

class ParentClass2():
    def parent2():
        print("Parent 2 is printing")

class ChildClass(ParentClass, ParentClass2):
    pass

x = ChildClass
x.parent1()
x.parent2()
Multiple inheritance in Python

In the above example, we’re getting access to multiple base classes functions from a ChildClass.

Hierarchical inheritance in Python

Hierarchical inheritance in Python is a situation when multiple child classes are inherited from a single parent class.

Heirarchical-diagram

Now let take a look at the example. We will create one parent class. And then will get access to its method from multiple child classes:

class Parent():
    def parent1():
        print("Parent is printing")

class ChildClass1(Parent):
    def child1():
        print("child 1 is printing")

class ChildClass2(Parent):
    def child2():
        print("child 2 is printing")

x = ChildClass1
x.parent1()
x.child1()

y=ChildClass2
y.parent1()
y.child2()
Heirarchical-program-in-python

As you can see, every child class has its own functions, but both of them inherit the same parent1() method from the base class.

Super() Function in Python

Calling a super() method in the child class constructor allows us to provide attributes to the constructor of the parent class. 

class Parent():
    def __init__(self, name):
        self.name = name

class Child(Parent):
    def __init__(self, childname):
        super().__init__(childname)

c = Child("Bashir")
print(f'name in Parent class: {c.name}')
Super() function in Python

In the example above, we are using the Child class constructor to set up name variable in the Parent class constructor.

Built-in class attributes in Python

There are some common built-in attributes that every class has. They can be accessed by using the dot (.) operator. Here’s a list of the important built-in attributes of the class object in Python:

  • __dict__ - Dictionary that contains the class namespace
  • __doc__ - Contains a documentation string of the class if defined.
  • __name__ - A variable that stores class name.
  • __module__ - Module name in which the class has been defined
  • __bases__ - A possibly empty tuple containing the base classes, in the order of their inheritance at the child class.

Encapsulation in Python

Encapsulation is one of the important concepts of Object-Oriented Programming in Python, which you can use to restrict access to methods and variables of the class.

Protecting class data in Python

An object’s attribute may or may not be visible outside of the class definition. To hide or protect base class variables or functions from access from the child class uses double underscore (__) as a prefix of the name of attribute or function. 

The following example demonstrates how to protect the data of the Parent class.

class Person:
   __age = 10
  
   def count(self):
      self.__age += 1
      print (self.__age)

Age = Person()
Age.count()
print (Age.__age)
Protecting class data in Python

The example above shows that you can get access to a variable __age only from the class method and not from the outside scope of the class.

Polymorphism in Python

The word "polymorphism" means multiple forms. In programming, polymorphism allows you to define the same function but with different parameters multiple times. Python will automatically detect which function to use based on the provided to the function arguments. For example, Python's built-in function len() can count elements in the list object or the number of characters in the string.

In the same way, polymorphism in Python classes allows us to define the same functions in each class and get access to them based on the class type:

class Person():
     def name(self):
         print("Bashir")
     def age(self):
         print("20")

class Person2():
     def name(self):
         print("Aqeel")
 
     def age(self):
         print("23")

FirstPerson = Person()
SecondPerson = Person2()

for x in (FirstPerson, SecondPerson):
    x.name()
    x.age()
Polymorphism-in-python-example

Python uses two different class types in the same way. Here, we have created a for loop that iterates through a tuple of objects. We call the methods without concern about which class type each object belongs to for every object from the tuple.

Additional classes use-cases in Python

This last section will cover some additional handy use-cases of Python classes that developers commonly use.

User-defined exception in Python

In Python, new custom exceptions can be defined by inheriting from the built-in Exception class. Developers usually defining custom exceptions to handle different errors in the program separately.

class MyCustomException(Exception):
    pass

Python __repr__() method

The Python __repr__() method is used to redefine a string representation of the class. It can only have one parameter self and should return a string. Usually, developers redefining __repr__() function to provide meaningful information about the data stored in the class.

class Person:
    def __init__(self, name):
        self.name = name
    
    def __repr__(self):
        return self.name

Alam = Person('Alam')
print(Alam)
repr__-method-in-python

In the example above, we are redefining the __repr__() function to return a name stored in the class.

Python issubclass() function

Python has a built-in issubclass() function allows us to check if one class (first argument) is inherited from another class (second argument).

class Person:
    def type(self):
        print("Parent class")

class Man(Person):
    def type(self):
        print("Child class")

print(issubclass(Man, Person))
Python issubclass() function

Summary

In this tutorial, we've covered classes in Python, class constructors, inheritance, polymorphism, and some important built-in properties of classes.

How useful was this post?

Click on a star to rate it!

Average rating 5 / 5. Vote count: 1

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Subscribe to our updates

Like this article?

Share on facebook
Share on Facebook
Share on twitter
Share on Twitter
Share on linkedin
Share on Linkdin
Share on pinterest
Share on Pinterest

Want to be an author of another post?

We’re looking for skilled technical authors for our blog!

Leave a comment

If you’d like to ask a question about the code or piece of configuration, feel free to use https://codeshare.io/ or a similar tool as Facebook comments are breaking code formatting.