Python Generics

Lesson Introduction

Welcome! In this lesson, we'll explore Python Generics. Generics let you write code that can handle different data types without duplicating code, making programs more flexible and reusable.

Think of generics like a Swiss Army knife. Instead of carrying a knife and a screwdriver separately, you have one tool that switches functions effortlessly. Sounds useful, right?

By the end of this lesson, you'll know how to define and use generics in Python. Let's get started!

Introduction to Generics in Python

Before diving into generics, let's revisit type annotations. Type annotations specify the kind of data a variable should hold, making our code more understandable and error-free.

Generics come in when we want a function or class to work with any data type. For example, a list can hold integers, strings, or objects. Wouldn't it be nice to write code that works with any type, just like a list? Generics help us achieve this.

Python's typing module provides tools for generics, like TypeVar, which lets us define a variable type. Let's explore how to use it in code.

Defining a Generic Class: Part 1

We define a generic class using TypeVar from the typing module. This acts as a placeholder for any data type. It's like labeling a blank space, which we'll fill with an actual data type later.

Here's the Stack class example:

from typing import TypeVar, Generic

# T can be any type
T = TypeVar('T')

class Stack(Generic[T]):
    def __init__(self) -> None:
        self.__container: list[T] = []

Here, we declare the T type and create a Stack class that stores a list of items of type T. It is achieved by defining the class as Generic[T]. Generic[T] is used to define a class or function that can operate on any data type specified by T. Using this trick, we can define Stacks that hold any data type; for example, we can create a Stack of integers or a Stack of strings.

Defining a Generic Class: Part 2

Continuing with our Stack class, let's implement its methods:

class Stack(Generic[T]):
    def __init__(self) -> None:
        self.__container: list[T] = []

    def push(self, item: T) -> None:
        self.__container.append(item)

    def pop(self) -> T:
        return self.__container.pop()

    def size(self) -> int:
        return len(self.__container)

Let's break down the methods in our Stack class:

  • push(self, item: T) -> None: Adds an item of type T to the stack.
  • pop(self) -> T: Removes and returns the last item in the stack. Note how we use -> T to specify that the returned item will be of the type T.
  • size(self) -> int: Returns the number of items in the stack.
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal