What Are Generics? |
generics allow functions and classes to be written which can operate on any data type while
maintaining clear type expectations generics define a placeholder for a type which is specified when the generic class is instantiated or call the generic function useful for creating reusable data structures and algorithms Python does not enforce type safety at runtime type hints with generics can greatly assist an IDE in providing better code completion, error checking, and documentation |
Why Use Generics? |
advantages of using generics
|
A Generic Stack |
to use generics in Python need to import the necessary components from the typing module the typing module is included in the standard library a stack is a common data structure that follows the Last In, First Out (LIFO) principle below
class Stack[T]: def __init__(self): self._items: list[T] = [] def push(self, item: T) -> None: self._items.append(item) def pop(self) -> T: return self._items.pop() def peek(self) -> T: return self._items[-1] def is_empty(self) -> bool: return len(self._items) == 0 def size(self) -> int: return len(self._items)create a stack of integers, strings, or any other type int_stack: Stack[int] = Stack() int_stack.push(1) int_stack.push(2) print(int_stack.pop()) # Output: 2 str_stack: Stack[str] = Stack() str_stack.push("hello") str_stack.push("world") print(str_stack.pop()) # Output: world |
A Generic Function |
generics are not limited to classes can also create generic functions an example of a simple generic function that returns the maximum of two values def get_max[T](a: T, b: T) -> T: return a if a > b else b print(get_max(10, 20)) # Output: 20 print(get_max("apple", "banana")) # Output: bananaT is a type variable representing the type of the arguments and return value the function get_max works with any type that supports the > operator |
Advanced Usage |
bounded type variables - can restrict a type variable to a certain subset of types
def concatenate[T:str](a: T, b: T) -> T: return a + b print(concatenate("hello", "world")) # Output: helloworldconstrained type variables - can constrain a number of types def mult[T:(int, float)](a: T, b: T) -> T: return a * b print(mult(10, 24.5)) # Output: 245.0generic inheritance - can create classes which inherit from generic classes class Container[T]: def __init__(self, value: T): self.value = value class IntContainer(Container[int]): pass int_container = IntContainer(42) print(int_container.value) # Output: 42 |