Generating lists populated with random objects
Requirements may vary so I find it hard to use with the "hardcoded" constructors. Instead I would define a function that accept such constructors as an argument.

I would also define the function returning the list-comprehension as an inner function so the off parameter is hidden from the public interface (the end-user does not need to know such implementation details). Besides, off is a terrible name for such variable when all it does it to track the recursion depth, better call it depth, then.

An other thing that could be worth taking as parameter (even though a sensible default would make sense most of the time) is the maximum length of the inner lists (and thus the maximum allowed recursion level):

import random
from string import digits


def fake_list(items, max_size=10):
    """Create a list populated with random objects constructed from `items`"""

    choices = (
            lambda _: random.choice(items)(),
            lambda depth: random_list(depth),
            lambda depth: tuple(random_list(depth)),
    )

    def random_list(depth):
        return [
                random.choice(choices)(depth + 1)
                for _ in range(max(random.randint(1, max_size) - depth, 0))
        ]

    if max_size &lt; 1:
        raise ValueError('minimal size of output should be at least 1')

    return random_list(0)


def test():
    constructors = [
        object,
        dict,
        lambda: bool(random.randint(0, 1)),
        lambda: random.randint(1, 1000),
        lambda: ''.join(
            random.choice(digits)
            for _ in range(random.randint(1, 10))),
    ]

    print(fake_list(constructors))


if __name__ == '__main__':
    test()


That way I can call:

fake_list([lambda: float('-inf'), lambda: range(random.randint(-100, -10), random.randint(10, 100)), set])


if I need to.