Understanding Typing Extensions in Python
The typing-extensions
module in Python is a lifesaver when working with Python’s type hinting capabilities. It provides backports of new type hinting features introduced in newer versions of Python, making it easier to use these features in older versions. This guide delves deep into the functionalities of typing-extensions
with practical examples to help you master its APIs and use them effectively in your Python applications.
Core Features of Typing Extensions
Here are some powerful APIs available in typing-extensions
:
1. Literal
The Literal
type restricts a value to a specific set of literal choices.
from typing_extensions import Literal def greet(status: Literal["success", "failure"]) -> str: if status == "success": return "Operation was successful!" elif status == "failure": return "Operation failed!" else: raise ValueError("Invalid status") print(greet("success")) # Output: Operation was successful!
2. TypedDict
TypedDict
allows you to define a dictionary with specific keys and their corresponding value types.
from typing_extensions import TypedDict class User(TypedDict): name: str age: int user: User = {"name": "Alice", "age": 25} print(user) # Output: {'name': 'Alice', 'age': 25}
3. Protocol
Use Protocol
to define structural subtyping (duck typing) in Python.
from typing_extensions import Protocol class Greeter(Protocol): def greet(self) -> str: pass class EnglishGreeter: def greet(self) -> str: return "Hello!" def print_greeting(greeter: Greeter) -> None: print(greeter.greet()) english_greeter = EnglishGreeter() print_greeting(english_greeter) # Output: Hello!
4. Final
Final
indicates that a variable, method, or class cannot be overridden or reassigned.
from typing_extensions import Final PI: Final = 3.14159 # PI = 3.14 # This will raise a mypy error (if type checking is enabled)
5. Annotated
An additional way to attach metadata to type hints.
from typing_extensions import Annotated def calculate_area(length: Annotated[int, "Length in meters"], width: Annotated[int, "Width in meters"]) -> int: return length * width print(calculate_area(5, 10)) # Output: 50
6. Self
Used for indicating the type of “self” in instance methods.
from typing_extensions import Self class Node: def __init__(self, value: int) -> None: self.value = value self.next: Self | None = None
7. get_origin
and get_args
Used to retrieve the origin and arguments of generic types.
from typing import Union from typing_extensions import get_origin, get_args my_type = Union[int, str] print(get_origin(my_type)) # Output:print(get_args(my_type)) # Output: ( , )
Building an Application with Typing Extensions
Let’s build a simple library management system using typing-extensions
.
from typing_extensions import TypedDict, Protocol, Literal class Book(TypedDict): title: str author: str status: Literal["available", "borrowed"] class LibraryManager(Protocol): def add_book(self, book: Book) -> None: pass def borrow_book(self, title: str) -> str: pass class Library(LibraryManager): def __init__(self) -> None: self.books: list[Book] = [] def add_book(self, book: Book) -> None: self.books.append(book) def borrow_book(self, title: str) -> str: for book in self.books: if book["title"] == title and book["status"] == "available": book["status"] = "borrowed" return f"You've borrowed '{title}'" return f"'{title}' is not available" library = Library() library.add_book({"title": "1984", "author": "George Orwell", "status": "available"}) library.add_book({"title": "Brave New World", "author": "Aldous Huxley", "status": "available"}) print(library.borrow_book("1984")) # Output: You've borrowed '1984' print(library.borrow_book("1984")) # Output: '1984' is not available
Conclusion
The typing-extensions
module is an indispensable tool when working with type hints in Python. Its versatile APIs ensure backward compatibility and deliver the power of advanced typing features even in older versions of Python. Whether you’re building small scripts or large-scale applications, typing-extensions
can help you write more robust and readable code. Start using it today!