def invert_dict(d):
    """Returns a new dict with keys as values and values as keys.

    Parameters
    ----------
    d : dict
        Input dictionary. If one value of the dictionary is a list or a tuple,
        each element of the sequence will be considered separately.

    Returns
    -------
    dict
        The new dictionary with d keys as values and d values as keys.
        In the case of duplicated d values, the value of the resulting key
        of the new dictionary will be a list with all the corresponding d keys.

    Examples
    --------
    >>> from secml.utils.dict_utils import invert_dict

    >>> a = {'k1': 2, 'k2': 2, 'k3': 1}
    >>> print(invert_dict(a))
    {1: 'k3', 2: ['k1', 'k2']}

    >>> a = {'k1': 2, 'k2': [2,3,1], 'k3': 1}
    >>> print(invert_dict(a))
    {1: ['k2', 'k3'], 2: ['k1', 'k2'], 3: 'k2'}

    """
    def tolist(x): return [x] if not isinstance(x, (list, tuple)) else list(x)
    new_d = {}
    for k in d.items():
        for v in tolist(k[1]):
            i = k[0]
            if v in new_d:
                # If the key has already been set create a list for the values
                i = tolist(i)
                i = tolist(new_d[v]) + i
            new_d[v] = i
    return new_d