{"id":2029,"date":"2026-01-11T13:03:14","date_gmt":"2026-01-11T00:03:14","guid":{"rendered":"https:\/\/www.ronella.xyz\/?p=2029"},"modified":"2026-01-12T08:52:22","modified_gmt":"2026-01-11T19:52:22","slug":"mastering-python-generics-a-comprehensive-guide","status":"publish","type":"post","link":"https:\/\/www.ronella.xyz\/?p=2029","title":{"rendered":"Python Generics"},"content":{"rendered":"<p>Python's generics system brings type safety to dynamic code, enabling reusable functions and classes that work across types while aiding static analysis tools like mypy. Introduced in Python 3.5 through PEP 483 and refined in versions like 3.12, generics use type variables without runtime overhead, leveraging duck typing for flexibility.<\/p>\n<h2>What Are Generics?<\/h2>\n<p>Generics parameterize types, allowing structures like lists or custom classes to specify element types at usage time. Core building block: <code>TypeVar<\/code> from <code>typing<\/code> (built-in since 3.12). They exist purely for static checking\u2014no enforcement at runtime, unlike Java's generics.<\/p>\n<pre><code class=\"language-python\">from typing import TypeVar\nT = TypeVar(&#039;T&#039;)  # Placeholder for any type<\/code><\/pre>\n<h2>Generic Functions in Action<\/h2>\n<p>Create flexible utilities by annotating parameters and returns with type variables. A practical example is a universal adder for any comparable types.<\/p>\n<pre><code class=\"language-python\">from typing import TypeVar\n\nT = TypeVar(&#039;T&#039;)  # Any type supporting +\n\ndef add(a: T, b: T) -&gt; T:\n    return a + b\n\n# Usage\nresult1: int = add(5, 3)           # Returns 8, type int\nresult2: str = add(&quot;hello&quot;, &quot;world&quot;)  # Returns &quot;helloworld&quot;, type str\nresult3: float = add(2.5, 1.7)     # Returns 4.2, type float<\/code><\/pre>\n<p>Mypy infers and enforces matching types\u2014<code>add(1, &quot;a&quot;)<\/code> fails checking. Another example: identity function.<\/p>\n<pre><code class=\"language-python\">def identity(value: T) -&gt; T:\n    return value<\/code><\/pre>\n<p>This works seamlessly across any type.<\/p>\n<h2>Building Generic Classes<\/h2>\n<p>Inherit from <code>Generic[T]<\/code> for type-aware containers (or use <code>class Stack[T]:<\/code> in 3.12+). A real-world <code>Result<\/code> type handles success\/error cases like Rust's <code>Result&lt;T, E&gt;<\/code>.<\/p>\n<pre><code class=\"language-python\">from typing import Generic, TypeVar\n\nT = TypeVar(&#039;T&#039;)  # Success type\nE = TypeVar(&#039;E&#039;)  # Error type\n\nclass Result(Generic[T, E]):\n    def __init__(self, value: T | None = None, error: E | None = None):\n        self.value = value\n        self.error = error\n        self.is_ok = error is None\n\n    def unwrap(self) -&gt; T | None:\n        if self.is_ok:\n            return self.value\n        raise ValueError(f&quot;Error: {self.error}&quot;)<\/code><\/pre>\n<pre><code class=\"language-python\">class Stack(Generic[T]):\n    def __init__(self) -&gt; None:\n        self.items: list[T] = []\n\n    def push(self, item: T) -&gt; None:\n        self.items.append(item)\n\n    def pop(self) -&gt; T:\n        return self.items.pop()<\/code><\/pre>\n<p><strong>Sample Usage:<\/strong><\/p>\n<pre><code class=\"language-python\"># Result usage\ndef divide(a: float, b: float) -&gt; Result[float, str]:\n    if b == 0:\n        return Result(error=&quot;Division by zero&quot;)\n    return Result(value=a \/ b)\n\nsuccess = divide(10, 2)\nprint(success.unwrap())  # 5.0\n\nfailure = divide(10, 0)\n# failure.unwrap() #raises ValueError\n\n# Stack usage\nint_stack: Stack[int] = Stack()\nint_stack.push(1)\nint_stack.push(42)\nprint(int_stack.pop())  # 42\n\nstr_stack: Stack[str] = Stack()\nstr_stack.push(&quot;hello&quot;)\nprint(str_stack.pop())  # &quot;hello&quot;<\/code><\/pre>\n<h2>Advanced Features<\/h2>\n<ul>\n<li><strong>Multiple TypeVars<\/strong>: <code>K = TypeVar(&#039;K&#039;); V = TypeVar(&#039;V&#039;)<\/code> for dict-like classes: <code>class Mapping(Generic[K, V]):<\/code>.<\/li>\n<li><strong>Bounds<\/strong>: <code>T = TypeVar(&#039;T&#039;, bound=str)<\/code> restricts to subclasses of <code>str<\/code>.<\/li>\n<li><strong>Variance<\/strong>: <code>TypeVar(&#039;T&#039;, contravariant=True)<\/code> for input-only types.<\/li>\n<\/ul>\n<h2>Mypy in Practice<\/h2>\n<p>Save the Stack class to <code>stack.py<\/code>. Run <code>mypy stack.py<\/code>\u2014no errors for valid code.<\/p>\n<p>Test errors: Add <code>stack: Stack[int] = Stack[str]()<\/code> then <code>mypy stack.py<\/code>:<\/p>\n<pre><code class=\"language-shell\">stack.py: error: Incompatible types in assignment (expression has type &quot;Stack[str]&quot;, variable has type &quot;Stack[int]&quot;)  [assignment]<\/code><\/pre>\n<p>Fix by matching types. Correct usage passes silently.<\/p>\n<h2>Practical Benefits and Tools<\/h2>\n<p>Generics catch errors early in IDEs and CI pipelines. Run <code>mypy script.py<\/code> to validate. No performance hit\u2014type hints erase at runtime. Ideal for libraries like FastAPI or Pydantic.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Python&#8217;s generics system brings type safety to dynamic code, enabling reusable functions and classes that work across types while aiding static analysis tools like mypy. Introduced in Python 3.5 through PEP 483 and refined in versions like 3.12, generics use type variables without runtime overhead, leveraging duck typing for flexibility. What Are Generics? Generics parameterize [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[88],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2029"}],"collection":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2029"}],"version-history":[{"count":2,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2029\/revisions"}],"predecessor-version":[{"id":2039,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2029\/revisions\/2039"}],"wp:attachment":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2029"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2029"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2029"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}