def check_type(obj, classinfo, name='object', msg=None):
    """Check the type of an object.

    >>> utils.check_type(1, str, 'num')
    Traceback (most recent call last):
      ...
    TypeError: the type of 'num' must be 'str', got 'int'
    >>> utils.check_type(1, (str, float), 'num')
    Traceback (most recent call last):
      ...
    TypeError: the type of 'num' must be one of 'str, float', got 'int'
    >>> utils.check_type(1, str, msg='wrong type for num')
    Traceback (most recent call last):
      ...
    TypeError: wrong type for num

    :param object obj: the object
    :param classinfo: see :func:`isinstance`
    :param str name: name shown in the exception message
    :param str msg: message for the exception
    :raises TypeError: if the check fails
    """
    if not isinstance(obj, classinfo):
        if not msg:
            if isinstance(classinfo, tuple):
                msg = 'the type of %r must be one of %r, got %r' % (name,
                    ', '.join(map(lambda x: x.__name__, classinfo)), obj.
                    __class__.__name__)
            else:
                msg = 'the type of %r must be %r, got %r' % (name,
                    classinfo.__name__, obj.__class__.__name__)
        raise TypeError(msg)
