Generics in Python

Our example demonstrates the use of generic functions and types in Python. Python has supported generics since version 3.5 through type hinting, and more advanced generic features were introduced in version 3.10.

from typing import TypeVar, Generic, List, Sequence, Any

# As an example of a generic function, `slices_index` takes
# a sequence of any comparable type and an element of that
# type and returns the index of the first occurrence of
# v in s, or -1 if not present.

T = TypeVar('T')

def slices_index(s: Sequence[T], v: T) -> int:
    for i, item in enumerate(s):
        if item == v:
            return i
    return -1

# As an example of a generic type, `LinkedList` is a
# singly-linked list with values of any type.

class LinkedList(Generic[T]):
    class Node(Generic[T]):
        def __init__(self, val: T):
            self.val = val
            self.next = None

    def __init__(self):
        self.head: LinkedList.Node[T] | None = None
        self.tail: LinkedList.Node[T] | None = None

    def push(self, v: T) -> None:
        new_node = self.Node(v)
        if self.tail is None:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            self.tail = new_node

    def all_elements(self) -> List[T]:
        elems = []
        current = self.head
        while current:
            elems.append(current.val)
            current = current.next
        return elems

def main():
    s = ["foo", "bar", "zoo"]

    # When using generic functions, Python's type inference
    # automatically determines the types.
    print("index of zoo:", slices_index(s, "zoo"))

    # We can also specify the types explicitly if needed.
    _ = slices_index[str](s, "zoo")

    lst = LinkedList[int]()
    lst.push(10)
    lst.push(13)
    lst.push(23)
    print("list:", lst.all_elements())

if __name__ == "__main__":
    main()

To run the program:

$ python generics.py
index of zoo: 2
list: [10, 13, 23]

This Python code demonstrates the use of generics through type hinting. The slices_index function is a generic function that works with any sequence of comparable items. The LinkedList class is a generic type that can hold elements of any type.

In Python, we use the TypeVar and Generic constructs from the typing module to define generic types. The T = TypeVar('T') creates a type variable that can be used in generic functions and classes.

The Sequence type hint is used instead of a specific list type to allow for any sequence-like object (lists, tuples, etc.). The Any type is used when we need to indicate that a value can be of any type.

Note that while Python’s type hints provide static type checking capabilities, they are optional and do not affect the runtime behavior of the program. Tools like mypy can be used to perform static type checking based on these hints.