Search code examples
pythonpython-typing

What is the benefit to using typing library classes vs. types in Python type hints?


I'm starting to learn type hints in Python to ease the future porting of code from Python to C. I am wondering what the difference is, if any, between using types directly in type hints vs. using the classes defined in the typing module.

For example, the difference between

def somefn(a: list[int]) -> tuple[str, int]:
    ...

and

from typing import List, Tuple

def somefn(a: List[int]) -> Tuple[str, int]:
    ...

It seems like some classes like Union, Any, Callable, and Iterable would be useful, but the utility of classes for data types that already exist as keywords in python is unclear to me.


Solution

  • Modern answer for development targeting Python 3.9 and higher

    As of 3.9, the standard collections can serve as type hints, so the typing types aren't strictly necessary, and are generally inferior to using the built-ins themselves; you can continue to use the typing types if you like (necessary for code that must run on pre-3.9 Python), but it's not necessary if you can rely on 3.9+.

    Remainder of answer covers the situation pre-3.9.


    Original answer for pre-3.9 development

    It's useful for writing annotations that can be legally evaluated; list[int] will explode if you try to actually run it, while typing.List[int] returns a new generic type that knows the type of both container and contents. This is particularly important in the case of type aliases, where a specialized version of a generic is defined at the top level, then reused as annotation further on:

    Vector = List[float]
    def scale(scalar: float, vector: Vector) -> Vector:
         ...
    

    is legal, while:

    Vector = list[float]
    def scale(scalar: float, vector: Vector) -> Vector:
         ...
    

    blows up in your face. You'll note that non-container/generic types typically don't have a typing type (exceptions like Text are for porting concerns), because type aliases would only use them as "leaf" type, not root or branch types.