Python 3.12 Generics: Streamlining Type-Safe Code

ArjanCodes////3 min read

Overview

introduces a major syntax overhaul for , making it easier than ever to write flexible, reusable code. Generics allow you to parameterize classes and functions with types, ensuring your data structures remain consistent without sacrificing the power of static type checking. Unlike using the any type, which effectively turns off type safety, generics preserve the relationship between inputs and outputs.

Prerequisites

To get the most out of this tutorial, you should have a basic understanding of class definitions and methods. Familiarity with is helpful, as generics are an extension of the broader typing system designed to catch bugs before they reach production.

Key Libraries & Tools

No external libraries are required. You only need the Python 3.12 standard library. Tools like or integrated development environment (IDE) hover features (like those in ) are essential for seeing these type checks in action.

Code Walkthrough

In previous versions, you had to import and define TypeVar. In 3.12, the syntax is significantly cleaner. We can define a generic Stack by placing the type parameter directly in brackets after the class name.

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

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

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

When you instantiate Stack[int](), the methods automatically adapt. The push method now explicitly expects an integer. This prevents a common headache: accidentally mixing strings into a list intended for numerical calculations.

Constrained Type Parameters

You can restrict what types a generic class accepts by using a tuple of allowed types. This is particularly useful when you need to ensure a class only handles numeric data for operations like summation.

class NumericStack[T: (int, float)](Stack[T]):
    def average(self) -> float:
        return sum(self.items) / len(self.items)

By defining T: (int, float), you tell the type checker that NumericStack[str] is invalid. Note that this is different from a Union. A Union[int, float] creates a stack that can contain a mix of both; a generic T restricted to (int, float) means the stack must be consistently all integers or all floats.

Tips & Gotchas

Always remember that Python remains a dynamically typed language at runtime. While your IDE will highlight a type violation in red if you pass a string to a Stack[int], the will still execute the code. Type hints are a development-time safety net, not a runtime enforcement mechanism.

Topic DensityMention share of the most discussed topics · 7 mentions across 7 distinct topics
14%· programming languages
14%· products
14%· programming languages
14%· products
14%· products
Other topics
29%
End of Article
Source video
Python 3.12 Generics: Streamlining Type-Safe Code

Python 3.12 Generics in a Nutshell

Watch

ArjanCodes // 6:22

On this channel, I post videos about programming and software design to help you take your coding skills to the next level. I'm an entrepreneur and a university lecturer in computer science, with more than 20 years of experience in software development and design. If you're a software developer and you want to improve your development skills, and learn more about programming in general, make sure to subscribe for helpful videos. I post a video here every Friday. If you have any suggestion for a topic you'd like me to cover, just leave a comment on any of my videos and I'll take it under consideration. Thanks for watching!

What they talk about
AI and Agentic Coding News
Who and what they mention most
Python
33.3%5
Python
20.0%3
Python
20.0%3
Pydantic
13.3%2
3 min read0%
3 min read