list, tuple, dict vs List, Tuple, Dict

Type Hints

What is the challenge

Due to the dynamic nature of Python, inferring or checking the type of an object being used is especially hard. This fact makes it hard for developers to understand what exactly is going on in code they haven’t written and, most importantly, for type checking tools found in many IDEs [PyCharm, PyDev come to mind] that are limited due to the fact that they don’t have any indicator of what type the objects are. As a result they resort to trying to infer the type with (as mentioned in the presentation) around 50% success rate.

Type hinting

Type hinting is a formal solution to statically indicate the type of a value within your Python code. It was specified in PEP 484 and introduced in Python 3.5.

Here’s an example of adding type information to a function. You annotate the arguments and the return value:

def greet(name: str) -> str:
    return "Hello, " + name

The name: str syntax indicates the name argument should be of type str. The -> syntax indicates the greet() function will return a string.


The below two statements can be found in the Type Hinting presentation:

Why Type Hints

  1. Helps Type Checkers: By hinting at what type you want the object to be the type checker can easily detect if, for instance, you’re passing an object with a type that isn’t expected.
  2. Helps with documentation: A third person viewing your code will know what is expected where, ergo, how to use it without getting them TypeErrors.
  3. Helps IDEs develop more accurate and robust tools: Development Environments will be better suited at suggesting appropriate methods when know what type your object is. You have probably experienced this with some IDE at some point, hitting the . and having methods/attributes pop up which aren’t defined for an object.

Why use Static Type Checkers?

  • Find bugs sooner: This is self evident, I believe.
  • The larger your project the more you need it: Again, makes sense. Static languages offer a robustness and control that dynamic languages lack. The bigger and more complex your application becomes the more control and predictability (from a behavioral aspect) you require.
  • Large teams are already running static analysis: I’m guessing this verifies the first two points.

Type Hinting with Mypy

mypy is an optional static type checker for Python that aims to combine the benefits of dynamic (or “duck”) typing and static typing. Mypy combines the expressive power and convenience of Python with a powerful type system and compile-time type checking. Mypy type checks standard Python programs; run them using any Python VM with basically no runtime overhead.

PEP 484 doesn’t enforce anything; it is simply setting a direction for function annotations and proposing guidelines for how type checking can/should be performed. You can annotate your functions and hint as many things as you want; your scripts will still run regardless of the presence of annotations because Python itself doesn’t use them.

As noted in the PEP, hinting types should generally take three forms:

  • Function annotations. PEP 3107
  • Stub files for built-in/user modules.
  • Special # type: type comments that complement the first two forms. (See: What are variable annotations in Python 3.6? for a Python 3.6 update for # type: type comments) Additionally, you’ll want to use type hints in conjunction with the new typing module introduced in Py3.5.
Additionally, you’ll want to use type hints in conjunction with the new typing module introduced in Py3.5.

The Typing Module

The Typing Module supports type hints as specified by PEP 484.

The typing module also supports:

  1. Type aliasing
  2. Type hinting for callback functions: Callable
  3. Generics - Abstract base classes have been extended to support subscription to denote expected types for container elements
  4. User-defined generic types - A user-defined class can be defined as a generic class
  5. Any type - Every type is a subtype of Any

Type Hinting Generics

from typing import List
class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:

List, Tuple/etc vs list/tuple/etc

typing.Tuple and typing.List are Generic types; this means you can specify what type their contents must be:

def f(points: Tuple[float, float]):
    return map(do_stuff, points)

This specifies that the tuple passed in must contain two float values.
You can’t do this with the built-in tuple type before Python 3.9.
Python 3.9 has the change that built-in types support hints

Summary

You should always pick the typing generics even when you are not currently restricting the contents. It is easier to add that constraint later with a generic type as the resulting change will be smaller.
From Python 3.9 (PEP 585) onwards tuple, list and various other classes are now generic types. Using these rather than their typing counterpart is now preferred.
You should always pick then non-typing generics whenever possible as the old typing.Tuple, typing.List and other generics are deprecated and will be removed in a later version of Python.

What are type hints in Python 3.5? PEP 585 – Type Hinting Generics In Standard Collections typing — Support for type hints Using List/Tuple/etc. from typing vs directly referring type as list/tuple/etc Static typing in python3: list vs List
PEP 483 – The Theory of Type Hints
PEP 484 – Type Hints
Type Hints - Guido van Rossum - PyCon 2015
Type Hinting
Type Checking With Mypy
mypy

Did you find this page helpful? Consider sharing it 🙌

Hongwei Li
Hongwei Li
Software, Networking

Always on the way - Coding, DevOps, Networking.