avatarSamer Sallam

Summary

This article provides a comprehensive guide on creating custom sequence classes in Python by overriding special methods, enabling features like indexing, slicing, and iteration.

Abstract

The article, part of a complete course in Python Object-Oriented Programming (OOP), focuses on teaching how to define a class that behaves like built-in Python sequences such as lists, tuples, and strings. It covers the concept of sequences special methods, which allow user

How to Create a Customized Sequence Class: Python OOP Complete Course — Part 18

Learn what sequences special methods in Python OOP are and how to override them.

Photo by Artur Voznenko on Unsplash

Before we start let me tell you that:

  • This article is a part of The Complete Course in Object-Oriented Programming in Python which you can find it here.
  • All resources are available in the “Resources” section below.

Introduction

Have you ever tried to define a class similar to the common sequences in Python like lists and dictionaries where the objects of these classes might support indexing, slicing, or iteration with for loop?

If you want to learn how to do this, you are in the right place.

Table of Contents

  1. What are Sequences Special Methods?
  2. Available Sequences Special Methods
  3. How to Override Sequences Special Methods?

1. What are Sequences Special Methods?

They are the methods that make your Python classes act like built-in sequences (dict, tuple, list, str, etc.. ).

These data types support indexing, iteration, membership operator (in), and other features. To make your object support these features, you have to override these sequences special methods.

2. Available Sequences Special Methods

Let us explore some of these functions.

  • __len__(): It is a method that makes your class object support the len() function.
  • __getitem__(): It is a method that makes your class object support indexing.
  • __setitem__(): It is a method that makes your class object mutable.

To keep the article clean and concise, all of the other methods’ definitions have been moved to this pdf file.

Photo by Tasso Mitsarakis on Unsplash

3. How to Override Sequences Special Methods?

First assume that you have a dataset of multiple text files, and you need a class to help you access these files easily and quickly (set and get).

Let us start by defining a simple class Datasetwith two instance attributes dataset_path, and samples.

import os
class Dataset:
    def __init__(self, dataset_path):
        self.dataset_path = dataset_path
        self.samples = os.listdir(dataset_path)
dataset = Dataset(r'E:\new deeep team\python-oop\Sections\[3] Special Methods (Dunder Methods) in Python OOP\[8] Sequences Special Methods\Article\dataset')
print(dataset.samples)

os.listdir() has been used to get the available files and folders in the selected location.

In this simple example, if you print dataset.samples you will get ['Doc 0.txt', 'Doc 1.txt', 'Doc 2.txt']. In other words, our dataset has three text files.

Now, let us check how many files are there in the dataset.

# Use len method
print(len(dataset))

Output:

TypeError                                 Traceback (most recent call last)
<ipython-input-6-78696a0140a2> in <module>
      1 # Use len method
----> 2 print(len(dataset))

TypeError: object of type 'Dataset' has no len()

You got TypeError because the object doesn’t support the method len().

Now let us make the Datasetobjects support that method by overriding the method __len__(). (As a reminder, samples attribute has a list of the dataset's files)

Output:

3

In this case, no more errors and you got 3 because it’s the number of text files.

Now, let us try to get access to the first file in this dataset.

print(dataset[0])

Output:

TypeError                                 Traceback (most recent call last)
<ipython-input-10-458771d72ad1> in <module>
----> 1 print(dataset[0])

TypeError: 'Dataset' object does not support indexing

You got TypeError because the Dataset object does not support indexing. To support indexing, you should override the method __getitem__().

Now let us override the __getitem__() method by doing the following steps:

  • All the samples have this pattern in the name Doc {number}.txt. Therefore, it will be added as a class attribute.
  • Next __getitem__()method will be overridden. This method accepts the object itself self and another parameter to represent the index index, and it returns the selected value.

Output:

Hi, I am Doc 2

You got the content of the third file in the dataset.

Another advantage of overriding __getitem__() method is that the class object becomes iterable. The next example shows how to use the class object with the for loop.

for txt_file in dataset:
    print(txt_file)

Output:

Hi, I am Doc 0
Hi, I am Doc 1
Hi, I am Doc 2

Now, let us see how we can update one of the file's contents using our class.

First, let us try the following code.

dataset[2] = "Hello, new value!!"

Output:

TypeError                                 Traceback (most recent call last)
<ipython-input-34-dcffeaa6152f> in <module>
----> 1 dataset[2] = "Hello, new value!!"

TypeError: 'Dataset' object does not support item assignment

You got a TypeError because the Dataset object doesn’t support the item assignment. In other words, Dataset class is immutable.

To convert it into a mutable class, you should override the method __setitem__(). Let us do that in the following code snippet. Refer to the last method, and see that we print the value before and after the update.

Output:

Before update
Hi, I am Doc 2

Updating a file

Afeter update
Hi I am update Doc 2

You can see now that the content of the third file has been updated.

In the previous example, you can see that __set__() has been overridden in a way allowing a new item to be created if it does not exist. Let us try that.

print(dataset[4])

Output:

FileNotFoundError                         Traceback (most recent call last)
<ipython-input-37-50f447d6a573> in <module>
----> 1 print(dataset[4])

<ipython-input-35-6d0cd1f29eb1> in __getitem__(self, index)
     13         file_name = self.sample_name.format(index)
     14         file_path = os.path.join(self.dataset_path, file_name)
---> 15         with open(file_path, 'r') as f:
     16             return f.read()
     17 

FileNotFoundError: [Errno 2] No such file or directory: 'E:\\new deeep team\\python-oop\\Sections\\[3] Special Methods (Dunder Methods) in Python OOP\\[8] Sequences Special Methods\\Article\\dataset\\Doc 4.txt'

You got FileNotFoundError, because there isn’t a file called Doc 4.txt.

Now, let us create the document Doc 4.txt

dataset[4] = "Hi, I am Doc 4"

print(dataset[4])

Output:

Creating a new file
Hi, I am Doc 4

As you can see, the file Doc 4 has been created and you have got its content.

Now, let us summarize what we have learned in this article.

Photo by Ann H on pexels
  • Sequences Special Methods are the methods that get your Python classes to act like built-in sequences (dict, tuple, list, str, etc.. ).
  • Using such methods will make your class objects support features like indexing, iteration with loops, membership operator…etc.

P.S.: A million thanks for your time reading my story. Before you leave let me mention quickly two points:

  • First, to get my posts in your inbox directly, would you please subscribe here, and you can follow me here.
  • Second, writers made thousands of $$ on Medium. To get unlimited access to Medium stories and start earning, sign up now for Medium membership which only costs $5 per month. By signing up with this link, you can directly support me at no extra cost to you.

To get back to the previous article, you can use the following link:

Part 17: What Happens Beyond the Scene When You Get, Set, or Delete an Instance Attribute

To move on to the next article, you can use the following link:

Part 19: How to Create a Custom Context Manager in Python OOP

Resources:

  • GitHub here.
  • Sequences Special Methods pdf file.
Python
Programming
Object Oriented
Software Engineering
Python Programming
Recommended from ReadMedium