Defining generic classes

The built-in collection classes are generic classes. Generic typeshave one or more type parameters, which can be arbitrary types. Forexample, Dict[int, str] has the type parameters int andstr, and List[int] has a type parameter int.

Programs can also define new generic classes. Here is a very simplegeneric class that represents a stack:

  1. from typing import TypeVar, Generic
  2.  
  3. T = TypeVar('T')
  4.  
  5. class Stack(Generic[T]):
  6. def __init__(self) -> None:
  7. # Create an empty list with items of type T
  8. self.items: List[T] = []
  9.  
  10. def push(self, item: T) -> None:
  11. self.items.append(item)
  12.  
  13. def pop(self) -> T:
  14. return self.items.pop()
  15.  
  16. def empty(self) -> bool:
  17. return not self.items

The Stack class can be used to represent a stack of any type:Stack[int], Stack[Tuple[int, str]], etc.

Using Stack is similar to built-in container types:

  1. # Construct an empty Stack[int] instance
  2. stack = Stack[int]()
  3. stack.push(2)
  4. stack.pop()
  5. stack.push('x') # Type error

Type inference works for user-defined generic types as well:

  1. def process(stack: Stack[int]) -> None: ...
  2.  
  3. process(Stack()) # Argument has inferred type Stack[int]

Construction of instances of generic types is also type checked:

  1. class Box(Generic[T]):
  2. def __init__(self, content: T) -> None:
  3. self.content = content
  4.  
  5. Box(1) # OK, inferred type is Box[int]
  6. Box[int](1) # Also OK
  7. s = 'some string'
  8. Box[int](s) # Type error