def unique_everseen(iterable, key=None):
    """
    Yield unique elements, preserving order.

        >>> list(unique_everseen('AAAABBBCCDAABBB'))
        ['A', 'B', 'C', 'D']
        >>> list(unique_everseen('ABBCcAD', str.lower))
        ['A', 'B', 'C', 'D']

    Sequences with a mix of hashable and unhashable items can be used.
    The function will be slower (i.e., `O(n^2)`) for unhashable items.

    """
    seenset = set()
    seenset_add = seenset.add
    seenlist = []
    seenlist_add = seenlist.append
    if key is None:
        for element in iterable:
            try:
                if element not in seenset:
                    seenset_add(element)
                    yield element
            except TypeError:
                if element not in seenlist:
                    seenlist_add(element)
                    yield element
    else:
        for element in iterable:
            k = key(element)
            try:
                if k not in seenset:
                    seenset_add(k)
                    yield element
            except TypeError:
                if k not in seenlist:
                    seenlist_add(k)
                    yield element
