Type Assertions in Python


Python is a dynamically typed language, meaning that it is not necessary to declare the types of variables. This makes Python programs concise and easy to write, but when writing significant code in Python I find myself wanting type declarations both as documentation and as runtime sanity checks.

Here's a simple way to add type declarations to Python in the form of runtime assertions. An object's type is declared by calling a function

_typecheck(argNum, object, typespec)

where object is the Python object to check and typespec is a type specification (defined below). argNum, if positive, is used in formatting error messages. For example, assuming the __debug__ system variable is True,

_typecheck(1, myVar, int)

checks that myVar is an integer. If it's not, an exception is raised:

TypeError: argument 1: expecting <type 'int'>

That's all there is to it. The nifty part is that type specifications are pretty flexible, being similar to Common Lisp type specifiers, which nicely correlates with the kinds of flexible data structures one typically encounters in Python. A type specification can be:

  • A simple type: int, str, bool, types.FunctionType, etc.
  • A list of type specifications, which describes a union of types. For example,
    [int, str, types.NoneType]
    describes a quantity that can be an integer, a string, or None.
  • A tuple of the form
    (tuple, typespec1, typespec2, ...)
    which describes a tuple and the types of the tuple's elements. For example,
    (tuple, int, str)
    describes a 2-element tuple consisting of an integer and a string.
  • A tuple of one of the forms
    (list, typespec)
    (list, typespec, min)
    (list, typespec, min, max)
    which describes a list, the type of the list's elements, and optional constraints on the length of the list. For example,
    (list, int, 3, 5)
    describes a list of between 3 and 5 integers.
  • A tuple of the form
    (dict, typespeckey, typespecvalue)
    which describes a dictionary and the types of the dictionary's keys and values. For example,
    (dict, int, str)
    describes a dictionary that maps integers to strings.
  • Any combination of the above. For example,
    [(list, (tuple, int, str), 1), types.NoneType]
    describes a quantity that can be either 1) a list of at least one element, each of which is a 2-tuple consisting of an integer and a string; or 2) None.

Here's the code: typecheck.py


Greg Janée
Created: 2005-02-07
Last modified: 2005-02-07 14:14