Comprehensive Guide to Typing Extensions and Its Powerful API Examples

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!

Leave a Reply

Your email address will not be published. Required fields are marked *