Question presented to candidate:
"Say I write def first(items: list) -> object. A caller passes a list of ints and gets back something the type checker only knows is an object. How do generics and TypeVar fix that, and what does a generic class look like?"
What a strong answer should cover:
- A type variable (
T = TypeVar("T")) is a placeholder the checker solves at each call, sofirst(list[int])returnsint: it links input and output types, whichAnycannot do - Generic classes subclass
Generic[T](or useclass Stack[T]:on 3.12+);Stack[int]is checked as a stack of ints - Bounds (
TypeVar("N", bound=float)) allow any subtype and keep it; constraints (TypeVar("S", str, bytes)) allow exactly one of a fixed list - Variance:
listis invariant (alist[int]is not alist[float]), read-only types likeSequenceare covariant; a mutable write is why - Type erasure at runtime:
Stack[int]()is a plainStack, the parameter is never checked, andisinstance(x, Stack[int])raisesTypeError
Code / implementation expected: Optional β a generic function such as first or a small generic container class, ideally with what a type checker infers for it.