import types


def flatten(struct, depth=-1):
    """
    Flattens and returns a complex structured object *struct* up to a certain *depth*. When *depth*
    is negative, *struct* is flattened entirely.
    """
    # generator are not considered as a flattening step, so pass the same depth
    if isinstance(struct, types.GeneratorType):
        return flatten(list(struct), depth=depth)

    # stopping criterion
    if depth == 0:
        return struct

    # actual flattening
    if isinstance(struct, dict):
        return flatten(struct.values(), depth=depth - 1)
    elif isinstance(struct, (list, tuple, set)):
        objs = []
        for obj in struct:
            objs.extend(flatten(obj, depth=depth - 1))
        return objs
    else:
        return [struct]